From dc745309201b228df4b01e3a9b0504c7f9a91af5 Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Thu, 9 May 2024 16:33:54 +0200 Subject: [PATCH 0001/1064] Better install instructions --- PLUGIN-README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PLUGIN-README.md b/PLUGIN-README.md index 96a87759..19ac7453 100644 --- a/PLUGIN-README.md +++ b/PLUGIN-README.md @@ -6,8 +6,7 @@ If you plan to use this plugin for personal purposes (not related to Firebird pr we recommend to use `pipx` to install `pytest` together with `firebird-qa` plugin: ``` -pipx install pytest -pipx inject pytest firebird-qa +pipx --include-deps firebird-qa ``` ## Configuration From 655577ae41d1bf5c596c509edeab128b3a6061a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 00:31:51 +0300 Subject: [PATCH 0002/1064] Added/Updated tests\bugs\core_4067_test.py: added combine_output in order to see STDERR content --- tests/bugs/core_4067_test.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4067_test.py b/tests/bugs/core_4067_test.py index 86fd1f1a..d18202a0 100644 --- a/tests/bugs/core_4067_test.py +++ b/tests/bugs/core_4067_test.py @@ -14,11 +14,10 @@ from firebird.qa import * db = db_factory() - -act = python_act('db') +act = python_act('db', substitutions = [('[ \t]+', ' ')]) expected_stdout = """ - X 1 + SQL_DIALECT 1 """ temp_db = temp_file('tmp_4067_1.fdb') @@ -26,11 +25,14 @@ @pytest.mark.version('>=3') def test_1(act: Action, temp_db: Path): test_script = f""" - set sql dialect 1; - create database 'localhost:{str(temp_db)}' page_size 4096 default character set win1251 collation win1251; - set list on; - select mon$sql_dialect as x from mon$database; -""" + set bail on; + set list on; + set sql dialect 1; + create database 'localhost:{str(temp_db)}' page_size 4096 default character set win1251 collation win1251; + select mon$sql_dialect as sql_dialect from mon$database; + commit; + drop database; + """ act.expected_stdout = expected_stdout - act.isql(switches=[], input=test_script, connect_db=False) + act.isql(switches = ['-q'], input=test_script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From e729ac1dd7af7576584a93c781b460392ca0bab4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 00:39:25 +0300 Subject: [PATCH 0003/1064] Added/Updated tests\bugs\core_1291_test.py: added combine_output in order to see STDERR content --- tests/bugs/core_1291_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/bugs/core_1291_test.py b/tests/bugs/core_1291_test.py index c1d36573..d0c5056e 100644 --- a/tests/bugs/core_1291_test.py +++ b/tests/bugs/core_1291_test.py @@ -881,8 +881,7 @@ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.isql(switches=[], - input=test_script % act.db.dsn, connect_db=False, charset='WIN1251') + act.isql(switches=['-q'], input = test_script % act.db.dsn, connect_db=False, charset='WIN1251', combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 21b880feae185229b30580e555355bc1cff8258b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 00:44:18 +0300 Subject: [PATCH 0004/1064] Added/Updated tests\bugs\core_4218_test.py: Refactored, plus added combine_output in order to see STDERR content --- tests/bugs/core_4218_test.py | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/bugs/core_4218_test.py b/tests/bugs/core_4218_test.py index 4eb0b2b5..41c85a13 100644 --- a/tests/bugs/core_4218_test.py +++ b/tests/bugs/core_4218_test.py @@ -15,37 +15,37 @@ db = db_factory() -test_user: User = user_factory('db', name='TMP_U4218', password='123') +tmp_user: User = user_factory('db', name='TMP_U4218', password='123') -act = python_act('db', substitutions=[('Commit current transaction \\(y/n\\)\\?', '')]) - -expected_stdout = """ - WHO_AM_I TMP_U4218 - WHO_IS_OWNER TMP_U4218 - WHO_AM_I SYSDBA - WHO_IS_OWNER TMP_U4218 -""" +act = python_act('db', substitutions = [('[ \t]+', ' ')]) test_db = temp_file('owner-db.fdb') @pytest.mark.version('>=3.0') -def test_1(act: Action, test_user: User, test_db: Path): +def test_1(act: Action, tmp_user: User, test_db: Path): with act.db.connect() as con: c = con.cursor() c.execute('grant create database to user TMP_U4218') con.commit() + test_script = f""" - create database 'localhost:{test_db}' user 'TMP_U4218' password '123'; - set list on; - set list on; -- Needed on Windows to really set list ON. - select current_user as who_am_i, mon$owner as who_is_owner from mon$database; - commit; - connect 'localhost:{test_db}'; - select current_user as who_am_i, mon$owner as who_is_owner from mon$database; - commit; - drop database; - quit; + create database 'localhost:{test_db}' user {tmp_user.name} password '{tmp_user.password}'; + set list on; + select current_user as who_am_i, mon$owner as who_is_owner from mon$database; + commit; + connect 'localhost:{test_db}'; + select current_user as who_am_i, mon$owner as who_is_owner from mon$database; + commit; + drop database; + quit; """ + expected_stdout = f""" + WHO_AM_I {tmp_user.name.upper()} + WHO_IS_OWNER {tmp_user.name.upper()} + WHO_AM_I SYSDBA + WHO_IS_OWNER {tmp_user.name.upper()} + """ + act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input=test_script) + act.isql(switches=['-q'], input=test_script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 88fa321aa6189a10f59b5842413824e1ca584688 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 00:48:04 +0300 Subject: [PATCH 0005/1064] Added/Updated tests\bugs\core_4933_test.py: added combine_output in order to see STDERR content. Added connect_db=False in order to avoid warning about rollback --- tests/bugs/core_4933_test.py | 172 ++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 84 deletions(-) diff --git a/tests/bugs/core_4933_test.py b/tests/bugs/core_4933_test.py index d52a74b3..20259aca 100644 --- a/tests/bugs/core_4933_test.py +++ b/tests/bugs/core_4933_test.py @@ -129,90 +129,94 @@ @pytest.mark.version('>=3.0.6') def test_1(act: Action, addi_script: Path, main_script: Path, tmp_db: Path): - addi_script.write_text(f""" - create database 'localhost:{tmp_db}' user {act.db.user} password '{act.db.password}'; - - recreate view v_check as - select - decode(t.mon$isolation_mode, 0,'consistency', 1,'snapshot', 2,'rc rec_vers', 3,'rc no_recv', 4,'rc read_cons', 'UNKNOWN') as tx_til_mon_trans, - rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') as tx_til_rdb_get_context, - decode(t.mon$lock_timeout, -1, 'wait', 0, 'no_wait', 'timeout ' || t.mon$lock_timeout) as tx_lock_timeout_mon_trans, - rdb$get_context('SYSTEM', 'LOCK_TIMEOUT') as tx_lock_timeout_rdb_get_context, - iif(t.mon$read_only=1,'read_only','read_write') as tx_read_only_mon_trans, - rdb$get_context('SYSTEM', 'READ_ONLY') as tx_read_only_rdb_get_context, - t.mon$auto_undo as tx_autoundo_mon_trans - -- only in FB 4.x+: ,t.mon$auto_commit as tx_autocommit_mon_trans - from mon$transactions t - where t.mon$transaction_id = current_transaction; - commit; - - select 'addi_script: create_new_db' as msg, v.* from v_check v; - rollback; - - connect 'localhost:{tmp_db}' user {act.db.user} password '{act.db.password}'; - select 'addi_script: reconnect' as msg, v.* from v_check v; - rollback; - - drop database; - """) - main_script.write_text(f""" - set list on; - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - recreate view v_check as - select - decode(t.mon$isolation_mode, 0,'consistency', 1,'snapshot', 2,'rc rec_vers', 3,'rc no_recv', 4,'rc read_cons', 'UNKNOWN') as tx_til_mon_trans, - rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') as tx_til_rdb_get_context, - decode(t.mon$lock_timeout, -1, 'wait', 0, 'no_wait', 'timeout ' || t.mon$lock_timeout) as tx_lock_timeout_mon_trans, - rdb$get_context('SYSTEM', 'LOCK_TIMEOUT') as tx_lock_timeout_rdb_get_context, - iif(t.mon$read_only=1,'read_only','read_write') as tx_read_only_mon_trans, - rdb$get_context('SYSTEM', 'READ_ONLY') as tx_read_only_rdb_get_context, - t.mon$auto_undo as tx_autoundo_mon_trans - -- only 4.x: ,t.mon$auto_commit as tx_autocommit_mon_trans - from mon$transactions t - where t.mon$transaction_id = current_transaction; - commit; - - select 'main_script: initial' as msg, v.* from v_check v; - commit; - - set keep_tran on; - commit; - - set transaction read only read committed record_version lock timeout 5 no auto undo; -- only in 4.x: auto commit; - - select 'main_script: started Tx' as msg, v.* from v_check v; - - commit; -------------------------------------------------------------------------------------- [ 1 ] - - select 'main_script: after_commit' as msg, v.* from v_check v; - - rollback; ------------------------------------------------------------------------------------ [ 2 ] - - select 'main_script: after_rollback' as msg, v.* from v_check v; - - rollback; - - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; --------------------------- [ 3 ] - - select 'main_script: after_reconnect' as msg, v.* from v_check v; - rollback; - - --################### - in {addi_script}; - --################### - - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; --------------------------- [ 5 ] - - select 'main_script: resume' as msg, v.* from v_check v; - rollback; - - set keep_tran off; - commit; - - select 'keep_tran: turned_off' as msg, v.* from v_check v; - commit; - """) + addi_script.write_text( + f""" + create database 'localhost:{tmp_db}' user {act.db.user} password '{act.db.password}'; + + recreate view v_check as + select + decode(t.mon$isolation_mode, 0,'consistency', 1,'snapshot', 2,'rc rec_vers', 3,'rc no_recv', 4,'rc read_cons', 'UNKNOWN') as tx_til_mon_trans, + rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') as tx_til_rdb_get_context, + decode(t.mon$lock_timeout, -1, 'wait', 0, 'no_wait', 'timeout ' || t.mon$lock_timeout) as tx_lock_timeout_mon_trans, + rdb$get_context('SYSTEM', 'LOCK_TIMEOUT') as tx_lock_timeout_rdb_get_context, + iif(t.mon$read_only=1,'read_only','read_write') as tx_read_only_mon_trans, + rdb$get_context('SYSTEM', 'READ_ONLY') as tx_read_only_rdb_get_context, + t.mon$auto_undo as tx_autoundo_mon_trans + -- only in FB 4.x+: ,t.mon$auto_commit as tx_autocommit_mon_trans + from mon$transactions t + where t.mon$transaction_id = current_transaction; + commit; + + select 'addi_script: create_new_db' as msg, v.* from v_check v; + rollback; + + connect 'localhost:{tmp_db}' user {act.db.user} password '{act.db.password}'; + select 'addi_script: reconnect' as msg, v.* from v_check v; + rollback; + + drop database; + """ + ) + main_script.write_text( + f""" + set list on; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + recreate view v_check as + select + decode(t.mon$isolation_mode, 0,'consistency', 1,'snapshot', 2,'rc rec_vers', 3,'rc no_recv', 4,'rc read_cons', 'UNKNOWN') as tx_til_mon_trans, + rdb$get_context('SYSTEM', 'ISOLATION_LEVEL') as tx_til_rdb_get_context, + decode(t.mon$lock_timeout, -1, 'wait', 0, 'no_wait', 'timeout ' || t.mon$lock_timeout) as tx_lock_timeout_mon_trans, + rdb$get_context('SYSTEM', 'LOCK_TIMEOUT') as tx_lock_timeout_rdb_get_context, + iif(t.mon$read_only=1,'read_only','read_write') as tx_read_only_mon_trans, + rdb$get_context('SYSTEM', 'READ_ONLY') as tx_read_only_rdb_get_context, + t.mon$auto_undo as tx_autoundo_mon_trans + -- only 4.x: ,t.mon$auto_commit as tx_autocommit_mon_trans + from mon$transactions t + where t.mon$transaction_id = current_transaction; + commit; + + select 'main_script: initial' as msg, v.* from v_check v; + commit; + + set keep_tran on; + commit; + + set transaction read only read committed record_version lock timeout 5 no auto undo; -- only in 4.x: auto commit; + + select 'main_script: started Tx' as msg, v.* from v_check v; + + commit; -------------------------------------------------------------------------------------- [ 1 ] + + select 'main_script: after_commit' as msg, v.* from v_check v; + + rollback; ------------------------------------------------------------------------------------ [ 2 ] + + select 'main_script: after_rollback' as msg, v.* from v_check v; + + rollback; + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; --------------------------- [ 3 ] + + select 'main_script: after_reconnect' as msg, v.* from v_check v; + rollback; + + --################### + in {addi_script}; + --################### + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; --------------------------- [ 5 ] + + select 'main_script: resume' as msg, v.* from v_check v; + rollback; + + set keep_tran off; + commit; + + select 'keep_tran: turned_off' as msg, v.* from v_check v; + commit; + """ + ) # Check act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input_file=main_script) + act.isql(switches = ['-q'], input_file = main_script, connect_db = False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 53c47013eadb23c7283cd9b5a45d42c790fb3e43 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 00:51:12 +0300 Subject: [PATCH 0006/1064] Added/Updated tests\bugs\core_5273_test.py: added combine_output in order to see STDERR content. Added connect_db=False in order to avoid warning about rollback --- tests/bugs/core_5273_test.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_5273_test.py b/tests/bugs/core_5273_test.py index 139e7b70..8855229b 100644 --- a/tests/bugs/core_5273_test.py +++ b/tests/bugs/core_5273_test.py @@ -46,19 +46,22 @@ @pytest.mark.version('>=4.0') def test_1(act: Action, temp_db: Path): sql_ddl = f""" - set list on; - set bail on; - create database 'localhost:{temp_db}'; - select mon$database_name from mon$database; - commit; - drop database; + set list on; + set bail on; + create database 'localhost:{temp_db}'; + select mon$database_name from mon$database; + commit; + drop database; """ # Get content of firebird.log BEFORE test log_before = act.get_firebird_log() + # Start trace with act.trace(db_events=trace, keep_log=False, database=temp_db.name): - act.isql(switches=[], input=sql_ddl) + act.isql(switches = ['-q'], input = sql_ddl, connect_db = False, combine_output = True) + # Get content of firebird.log AFTER test log_after = act.get_firebird_log() + # Check assert list(unified_diff(log_before, log_after)) == [] From a81094d88fa8dc53e70ede2de8d3ee8e7a038327 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:10:20 +0300 Subject: [PATCH 0007/1064] Added/Updated tests\bugs\core_5495_test.py: Refactored, plus added combine_output in order to see STDERR content --- tests/bugs/core_5495_test.py | 45 +++++++++++++++++------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_5495_test.py b/tests/bugs/core_5495_test.py index 3b70731e..fef018db 100644 --- a/tests/bugs/core_5495_test.py +++ b/tests/bugs/core_5495_test.py @@ -17,38 +17,35 @@ JIRA: CORE-5495 FBTEST: bugs.core_5495 """ +import locale import pytest from firebird.qa import * db = db_factory() +act = python_act('db', substitutions = [('TCPv(4|6)', 'TCP'),('[ \t]+', ' ')]) -test_user = user_factory('db', name='tmp$c5495', password='123', plugin='Legacy_UserManager') - -test_script = """ - set list on; - set bail on; - connect '$(DSN)' user tmp$c5495 password '123'; - --select mon$user,mon$remote_address,mon$remote_protocol,mon$client_version,mon$remote_version,mon$auth_method from mon$attachments - select mon$user,mon$remote_protocol,mon$auth_method from mon$attachments - where mon$attachment_id=current_connection; - commit; - connect '$(DSN)' user SYSDBA password 'masterkey'; - commit; -""" - -act = isql_act('db', test_script, substitutions=[('TCPv.*', 'TCP'), - ('Commit current transaction \\(y/n\\)\\?', '')]) - -expected_stdout = """ - MON$USER TMP$C5495 - MON$REMOTE_PROTOCOL TCP - MON$AUTH_METHOD Legacy_Auth -""" +tmp_user = user_factory('db', name='tmp$c5495', password='123', plugin='Legacy_UserManager') @pytest.mark.version('>=4.0') -def test_1(act: Action, test_user: User): +def test_1(act: Action, tmp_user: User): + + test_script = f""" + set list on; + set bail on; + connect '{act.db.dsn}' user {tmp_user.name} password '{tmp_user.password}'; + select mon$user,mon$remote_protocol,mon$auth_method from mon$attachments + where mon$attachment_id=current_connection; + commit; + """ + + expected_stdout = f""" + MON$USER {tmp_user.name.upper()} + MON$REMOTE_PROTOCOL TCP + MON$AUTH_METHOD Legacy_Auth + """ + act.expected_stdout = expected_stdout - act.execute() + act.isql(switches = ['-q'], input = test_script, connect_db = False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From bc76e00aa23b2dc122b0131f27055f1e12f7eaba Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:13:53 +0300 Subject: [PATCH 0008/1064] Added/Updated tests\bugs\core_5630_test.py: Refactored, plus added combine_output in order to see STDERR content --- tests/bugs/core_5630_test.py | 68 ++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/tests/bugs/core_5630_test.py b/tests/bugs/core_5630_test.py index e0a7545c..d89cf2b7 100644 --- a/tests/bugs/core_5630_test.py +++ b/tests/bugs/core_5630_test.py @@ -9,6 +9,7 @@ JIRA: CORE-5630 FBTEST: bugs.core_5630 """ +import locale import pytest from pathlib import Path @@ -43,37 +44,38 @@ @pytest.mark.version('>=3.0.3') def test_1(act: Action, fdb_file: Path, fbk_file: Path, shd_file: Path): init_ddl = f""" - set bail on; - set list on; - - create database 'localhost:{fdb_file}' user '{act.db.user}' password '{act.db.password}'; - - recreate table test(s varchar(30)); - commit; - - create or alter view v_shadow_info as - select - rdb$file_sequence -- 0 - ,rdb$file_start -- 0 - ,rdb$file_length -- 0 - ,rdb$file_flags -- 1 - ,rdb$shadow_number -- 1 - from rdb$files - where lower(rdb$file_name) containing lower('core_5630.shd') - ; - - insert into test select 'line #' || lpad(row_number()over(), 3, '0' ) from rdb$types rows 200; - commit; - - create shadow 1 '{shd_file}'; - commit; - set list on; - select * from v_shadow_info; - select hash( list(s) ) as s_hash_before from test; - quit; + set bail on; + set list on; + + create database 'localhost:{fdb_file}' user {act.db.user} password '{act.db.password}'; + + recreate table test(s varchar(30)); + commit; + + create or alter view v_shadow_info as + select + rdb$file_sequence -- 0 + ,rdb$file_start -- 0 + ,rdb$file_length -- 0 + ,rdb$file_flags -- 1 + ,rdb$shadow_number -- 1 + from rdb$files + where lower(rdb$file_name) containing lower('core_5630.shd') + ; + + insert into test select 'line #' || lpad(row_number()over(), 3, '0' ) from rdb$types rows 200; + commit; + + create shadow 1 '{shd_file}'; + commit; + set list on; + select * from v_shadow_info; + select hash( list(s) ) as s_hash_before from test; + quit; """ + act.expected_stdout = expected_stdout_a - act.isql(switches=['-q'], input=init_ddl) + act.isql(switches=['-q'], input = init_ddl, connect_db=False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout # with act.connect_server() as srv: @@ -84,6 +86,9 @@ def test_1(act: Action, fdb_file: Path, fbk_file: Path, shd_file: Path): shd_file.unlink() # act.reset() + + #----------------------------------------------------------------------------------- + act.gbak(switches=['-c', '-use_all_space', str(fbk_file), act.get_dsn(fdb_file)]) # Check that we have the same data in DB tables sql_text = """ @@ -92,6 +97,9 @@ def test_1(act: Action, fdb_file: Path, fbk_file: Path, shd_file: Path): select hash( list(s) ) as s_hash_after from test; """ act.reset() + + #----------------------------------------------------------------------------------- act.expected_stdout = expected_stdout_b - act.isql(switches=['-q', act.get_dsn(fdb_file)], input=sql_text, connect_db=False) + act.isql(switches=['-q', act.get_dsn(fdb_file)], input=sql_text, connect_db=False, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout From 6d39fdf0b366ae1c0fb898071f93cd3ea507b5fd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:17:03 +0300 Subject: [PATCH 0009/1064] Added/Updated tests\bugs\core_6469_test.py: Refactored, plus added combine_output in order to see STDERR content --- tests/bugs/core_6469_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_6469_test.py b/tests/bugs/core_6469_test.py index 7bbc7d5b..13977076 100644 --- a/tests/bugs/core_6469_test.py +++ b/tests/bugs/core_6469_test.py @@ -182,7 +182,7 @@ def run_script(act: Action, tmp_file: Path): """ tmp_file.write_text(script) - act.isql(switches=['-n'], input_file = tmp_file, connect_db = False, credentials = False) + act.isql(switches=['-n', '-q'], input_file = tmp_file, connect_db = False, credentials = False) @pytest.mark.version('>=4.0') @pytest.mark.platform('Windows') @@ -268,7 +268,7 @@ def test_1(act: Action, test_role: Role, tmp_file: Path, capsys): @pytest.mark.platform('Linux') def test_2(act: Action, test_role: Role, capsys): with act.trace(db_events=trace_lin): - act.isql(switches=['-n'], input=test_script_lin) + act.isql(switches=['-n', '-q'], input = test_script_lin) # process trace for line in act.trace_log: From f01cc06f40f7553ca895894dc3780e6219e6f6fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:19:51 +0300 Subject: [PATCH 0010/1064] Added/Updated tests\bugs\core_6517_test.py: Refactored, plus added combine_output in order to see STDERR content --- tests/bugs/core_6517_test.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_6517_test.py b/tests/bugs/core_6517_test.py index 20467b7e..db666ff2 100644 --- a/tests/bugs/core_6517_test.py +++ b/tests/bugs/core_6517_test.py @@ -3,15 +3,15 @@ """ ID: issue-6746 ISSUE: 6746 -TITLE: Regression: CREATE DATABASE fails with 'Token unknown' error when DB name is - enclosed in double quotes and 'DEFAULT CHARACTER SET' is specified after DB name +TITLE: Regression: CREATE DATABASE fails with 'Token unknown' error when DB name is enclosed in double quotes and 'DEFAULT CHARACTER SET' is specified after DB name DESCRIPTION: JIRA: CORE-6517 FBTEST: bugs.core_6517 """ +import locale +from pathlib import Path import pytest -from pathlib import Path from firebird.qa import * db = db_factory() @@ -22,5 +22,7 @@ @pytest.mark.version('>=3.0.8') def test_1(act: Action, test_db: Path): - act.isql(switches=[], input=f'create database "{act.get_dsn(test_db)}" default character set utf8;', - connect_db=False) + test_sql = f""" + create database "{act.get_dsn(test_db)}" default character set utf8; + """ + act.isql(switches = ['-q'], input = test_sql, connect_db = False, combine_output = True, io_enc = locale.getpreferredencoding()) From 32b22cb8221337af78a5072cf9222b2f66ec8101 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:22:26 +0300 Subject: [PATCH 0011/1064] Added/Updated tests\functional\database\create\test_01.py: Refactored, plus added combine_output in order to see STDERR content --- tests/functional/database/create/test_01.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/functional/database/create/test_01.py b/tests/functional/database/create/test_01.py index 92d2c6f0..5eb76318 100644 --- a/tests/functional/database/create/test_01.py +++ b/tests/functional/database/create/test_01.py @@ -25,14 +25,14 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): script = f""" - create database '{act.db.dsn}' user '{act.db.user}' - password '{act.db.password}' set names 'win1251' default character set utf8 ; - set list on ; - select c.rdb$character_set_name as client_char_set, r.rdb$character_set_name as db_char_set - from mon$attachments a join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id - cross join rdb$database r - where a.mon$attachment_id = current_connection ; + create database '{act.db.dsn}' user '{act.db.user}' + password '{act.db.password}' set names 'win1251' default character set utf8 ; + set list on ; + select c.rdb$character_set_name as client_char_set, r.rdb$character_set_name as db_char_set + from mon$attachments a join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + cross join rdb$database r + where a.mon$attachment_id = current_connection ; """ act.expected_stdout = expected_stdout - act.isql(switches=[], input=script, connect_db=False) + act.isql(switches = ['-q'], input=script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 2416966a60b02fbff12c0605ba4082158377cc58 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:23:16 +0300 Subject: [PATCH 0012/1064] Added/Updated tests\functional\database\create\test_08.py: refactored, plus added combine_output in order to see STDERR content --- tests/functional/database/create/test_08.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/database/create/test_08.py b/tests/functional/database/create/test_08.py index 38767e64..dd781a04 100644 --- a/tests/functional/database/create/test_08.py +++ b/tests/functional/database/create/test_08.py @@ -38,5 +38,5 @@ def test_1(act: Action): from rdb$files ; """ act.expected_stdout = expected_stdout - act.isql(switches=[], input=script, connect_db=False) + act.isql(switches = ['-q'], input=script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 0696101171c7ab94a88d7da9e175368f181cb614 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:24:09 +0300 Subject: [PATCH 0013/1064] Added/Updated tests\functional\database\create\test_09.py: refactored, plus added combine_output in order to see STDERR content --- tests/functional/database/create/test_09.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/database/create/test_09.py b/tests/functional/database/create/test_09.py index 4d2b0d3e..862a862f 100644 --- a/tests/functional/database/create/test_09.py +++ b/tests/functional/database/create/test_09.py @@ -48,5 +48,5 @@ def test_1(act: Action): from rdb$files ; """ act.expected_stdout = expected_stdout - act.isql(switches=[], input=script, connect_db=False) + act.isql(switches = ['-q'], input=script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 283db629a7373bb841d4d756da565c9f0f700a7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 10 May 2024 01:24:49 +0300 Subject: [PATCH 0014/1064] Added/Updated tests\functional\database\create\test_10.py: refactored, plus added combine_output in order to see STDERR content --- tests/functional/database/create/test_10.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/database/create/test_10.py b/tests/functional/database/create/test_10.py index 003ed6a5..d488fbf7 100644 --- a/tests/functional/database/create/test_10.py +++ b/tests/functional/database/create/test_10.py @@ -47,5 +47,5 @@ def test_1(act: Action): from rdb$files ; """ act.expected_stdout = expected_stdout - act.isql(switches=[], input=script, connect_db=False) + act.isql(switches = ['-q'], input=script, connect_db=False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 7a99c91a2977c4bfe5ebce83920a3dd8deb7adfc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 11 May 2024 11:46:47 +0300 Subject: [PATCH 0015/1064] Added/Updated tests\bugs\gh_8100_test.py: Checked on intermediate snapshot 6.0.0.345 #17b007d -- all OK. --- tests/bugs/gh_8100_test.py | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/bugs/gh_8100_test.py diff --git a/tests/bugs/gh_8100_test.py b/tests/bugs/gh_8100_test.py new file mode 100644 index 00000000..5d373582 --- /dev/null +++ b/tests/bugs/gh_8100_test.py @@ -0,0 +1,53 @@ +#coding:utf-8 + +""" +ID: issue-8100 +ISSUE: 8100 +TITLE: The isc_array_lookup_bounds function returns invalid values for low and high array bounds +DESCRIPTION: + Test verifies ability to create table with array-type column, store data in it and obtain array by query. + Script based on example provided in firebird-driver doc: + https://firebird-driver.readthedocs.io/en/latest/usage-guide.html#firebird-array-type +NOTES: + [11.05.2024] pzotov + Confirmed problem on 6.0.0.344: got "ValueError: Incorrect ARRAY field value" + Checked on intermediate snapshot 6.0.0.345 #17b007d -- all OK. +""" + +import pytest +from pathlib import Path +from firebird.qa import * + +db = db_factory() +act = python_act('db', substitutions = [('[ \t]+', ' ')]) + +@pytest.mark.version('>=6') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + cur = con.cursor() + con.execute_immediate("recreate table array_table (id int generated by default as identity constraint pk_arr primary key, arr int[3,4])") + con.commit() + + data = ( + [ [87, 13, 16, 19], [25, 52, 73, 24], [81, 92, 63, 14] ] + ,[ [21, 79, 63, 57], [34, 42, 13, 34], [71, 15, 73, 34] ] + ,[ [31, 33, 55, 47], [17, 22, 33, 14], [91, 21, 93, 24] ] + ) + + ps = cur.prepare("insert into array_table(arr) values (?)") + for x in data: + cur.execute(ps, (x,)) + con.commit() + + cur.execute("select id, arr from array_table order by (arr[1,2]) desc") + for r in cur: + print(r[0], r[1]) + + act.expected_stdout = """ + 2 [[21, 79, 63, 57], [34, 42, 13, 34], [71, 15, 73, 34]] + 3 [[31, 33, 55, 47], [17, 22, 33, 14], [91, 21, 93, 24]] + 1 [[87, 13, 16, 19], [25, 52, 73, 24], [81, 92, 63, 14]] + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From d738f21cc9380b428b0e20fd60a8690398bec3a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 11 May 2024 11:51:55 +0300 Subject: [PATCH 0016/1064] Added/Updated tests\bugs\gh_8100_test.py: Reduced min_version to 5.0.1. Checked on 5.0.1.1394 #aa3cafb - all OK. --- tests/bugs/gh_8100_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_8100_test.py b/tests/bugs/gh_8100_test.py index 5d373582..bbd7291f 100644 --- a/tests/bugs/gh_8100_test.py +++ b/tests/bugs/gh_8100_test.py @@ -10,8 +10,8 @@ https://firebird-driver.readthedocs.io/en/latest/usage-guide.html#firebird-array-type NOTES: [11.05.2024] pzotov - Confirmed problem on 6.0.0.344: got "ValueError: Incorrect ARRAY field value" - Checked on intermediate snapshot 6.0.0.345 #17b007d -- all OK. + Confirmed problem on 5.0.0.1391, 6.0.0.344: got "ValueError: Incorrect ARRAY field value" + Checked on 6.0.0.345 #17b007d, 5.0.1.1394 #aa3cafb - all OK. """ import pytest @@ -21,7 +21,7 @@ db = db_factory() act = python_act('db', substitutions = [('[ \t]+', ' ')]) -@pytest.mark.version('>=6') +@pytest.mark.version('>=5.0.1') def test_1(act: Action, capsys): with act.db.connect() as con: From c8c97906a1e0c39f9265160e484e36668ce4650e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 13 May 2024 21:37:33 +0300 Subject: [PATCH 0017/1064] Added/Updated tests\bugs\core_6038_test.py: adjusted TITLE, DESCR and NOTES. --- tests/bugs/core_6038_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_6038_test.py b/tests/bugs/core_6038_test.py index df83a78b..aa048483 100644 --- a/tests/bugs/core_6038_test.py +++ b/tests/bugs/core_6038_test.py @@ -4,6 +4,7 @@ ID: issue-6288 ISSUE: 6288 TITLE: Srp user manager sporadically creates users which can not attach +DESCRIPTION: Explanation of bug nature was provided by Alex, see letter 05-jun-19 13:51. Some iteration failed with probability equal to occurence of 0 (zero) in the highest BYTE of some number. Byte is 8 bit ==> this probability is 1/256. @@ -12,12 +13,10 @@ Because of time (speed) it was decided to run only 256 iterations. If bug will be 'raised' somewhere then this number is enough to catch it after 2-3 times of test run. - +NOTES: Reproduced on WI-V3.0.5.33118, date: 11-apr-19 (got fails not late than on 250th iteration). Works fine on WI-V3.0.5.33139, date: 04-apr-19. -NOTES: A new bug was found during this test implementation, affected 4.0 Classic only: CORE-6080. -DESCRIPTION: JIRA: CORE-6038 FBTEST: bugs.core_6038 """ From b3b85d97621c18f84dd3b083f9aba0f2aa697c1b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 13 May 2024 22:24:18 +0300 Subject: [PATCH 0018/1064] Added/Updated tests\bugs\gh_7255_test.py: Confirmed bug on 5.0.0.599, Classic. LINUX only. Checked on 5.0.0.1397, 4.0.5.3098. ACHTUNG: READ NOTES FOR THIS TEST. --- tests/bugs/gh_7255_test.py | 144 +++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 tests/bugs/gh_7255_test.py diff --git a/tests/bugs/gh_7255_test.py b/tests/bugs/gh_7255_test.py new file mode 100644 index 00000000..8ebea200 --- /dev/null +++ b/tests/bugs/gh_7255_test.py @@ -0,0 +1,144 @@ +#coding:utf-8 + +""" +ID: issue-7255 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7255 +TITLE: READ COMMITTED READ CONSISTENCY mode is broken in Classic / SuperClassic on Linux (the newly created users are not visible to execute statement) +DESCRIPTION: + Issue can be reproduced only if firebird.conf contains ReadConsistency = 1. + Problem will NOT appear if this parameter is set to 0 and we start transactions as 'READ COMMITTED READ CONSISTENCY'. + Because of that, it was decided to make copy of firebird.conf, read its content and remote any line with 'ReadConsistency'. + Then we add new line with ReadConsistency = 1 and OVERWRITE firebird.conf. + After this, we run ISQL with script similar to provided in the ticket. + Output must display name of new user and TIL of his transaction ('read committed read consistency') that is seen in procedure sp_main. + Finally, we revert changes in firebir.conf using its original copy. + All these actions are enclosed in the try/except/finally block. +NOTES: + ### ACHTUNG ### + Test tries temporary to change content of firebird.conf. In any outcome, this content will be restored at final point. + + Confirmed bug on 5.0.0.599, Classic. LINUX only. + Checked on 5.0.0.1397, 4.0.5.3098. + + Command switch '--disable-db-cache' must be used if this test is running under 5.0.0.999 after some fresh FB with same ODS was tested. + Otherwise "internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 293)" will raise. + Example: + /opt/distr/venv/bin/pytest --disable-db-cache -vv --tb=long --server qa_rundaily_FB50 tests/bugs/gh_7255_test.py +""" +import shutil +import pytest +import locale +import re +import time +import platform +from pathlib import Path +from firebird.qa import * + +db = db_factory(async_write = True) +act = python_act('db', substitutions = [('[ \t]+', ' ')]) + +fbcfg_bak = temp_file('firebird.conf') +p_read_consist_param = re.compile('ReadConsistency\\s*=\\s*(0|1)', re.IGNORECASE) +TMP_USR_NAME = 'tmp$7255' + +@pytest.mark.skipif(platform.system() == 'Windows', reason='Reproduced on Linux only.') +@pytest.mark.version('>=4.0.3') +def test_1(act: Action, fbcfg_bak: Path, capsys): + + if act.vars['server-arch'].lower() != 'classic': + pytest.skip('Can be reproduced only for Servermode = Classic.') + + fbcfg_file = act.vars['home-dir'] / 'firebird.conf' + shutil.copy2(fbcfg_file, fbcfg_bak) + + try: + fbcfg_ini = fbcfg_file.read_text(encoding='utf-8').splitlines() + fbcfg_new = [] + for x in fbcfg_ini: + if p_read_consist_param.search(x): + pass + else: + fbcfg_new.append(x) + + fbcfg_new.append('ReadConsistency = 1') + fbcfg_file.write_text('\n'.join(fbcfg_new), encoding='utf-8' ) + + test_sql = f""" + set list on; + commit; + SET KEEP_TRAN_PARAMS ON; + SET TRANSACTION READ COMMITTED READ CONSISTENCY; + + create or alter user {TMP_USR_NAME} password '123'; + commit; + + set term ^; + create or alter procedure sp_main( + a_usr varchar(31), a_pwd varchar(31) + ) returns( + who varchar(50) + ,til varchar(50) + ) as + begin + for + execute statement + q'#select #' + || q'# a.mon$user as who #' + || q'# ,decode( #' + || q'# t.mon$isolation_mode #' + || q'# ,0, 'snapshot table stability' #' + || q'# ,1, 'concurrency (snapshot)' #' + || q'# ,2, 'read committed record version' #' + || q'# ,3, 'read committed no record version' #' + || q'# ,4, 'read committed read consistency' #' + || q'# ) as til #' + || q'#from mon$attachments a #' + || q'#join mon$transactions t on a.mon$attachment_id = t.mon$attachment_id #' + || q'#where a.mon$attachment_id = current_connection and t.mon$state = 1 #' + as user a_usr password a_pwd + into who, til + do + suspend; + end + ^ + set term ;^ + commit; + + grant execute on procedure sp_main to {TMP_USR_NAME}; + commit; + + -- wait 10 seconds and it will work + + set term ^; + execute block returns( + who varchar(50) + ,til varchar(50) + ) as + begin + for + execute statement ('select who, til from sp_main(:u, :p)') ( u := '{TMP_USR_NAME}', p := '123' ) + into who, til + do + suspend; + end + ^ + set term ;^ + commit; + + drop user {TMP_USR_NAME}; + commit; + """ + + act.isql(switches = ['-q'], input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) + + except OSError as e: + print(e) + finally: + shutil.copy2(fbcfg_bak, act.vars['home-dir'] / 'firebird.conf') + + act.expected_stdout = f""" + WHO {TMP_USR_NAME.upper()} + TIL read committed read consistency + """ + # act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From f409f2a7c9982882b09e215594191c76fb5edf29 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 14 May 2024 15:52:07 +0300 Subject: [PATCH 0019/1064] Deleted core_5201_test.py which occasionally was placed in firebird-QA home dir --- core_5201_test.py | 80 ----------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 core_5201_test.py diff --git a/core_5201_test.py b/core_5201_test.py deleted file mode 100644 index 8136705e..00000000 --- a/core_5201_test.py +++ /dev/null @@ -1,80 +0,0 @@ -#coding:utf-8 - -""" -ID: issue-5482 -ISSUE: 5482 -TITLE: Return nonzero result code when restore fails on activating and creating deferred user index -DESCRIPTION: - According to Alex response on letter 25-apr-2016 19:15, zero retcode returned ONLY when restore - was done WITH '-verbose' switch, and this was fixed. When restore performed without additional - switches, retcode was 1. - - We create table with UNIQUE computed-by index which expression refers to other table (Firebird allows this!). - Because other table (test_2) initially is empty, index _can_ be created. But after this we insert record into - this table and do commit. Since that moment backup of this database will have table test_1 but its index will - NOT be able to restore (unless '-i' switch specified). - We will use this inability of restore index by checking 'gbak -rep -v ...' return code: it should be NON zero. - If code will skip exception then this will mean FAIL of test. -JIRA: CORE-5201 -FBTEST: bugs.core_5201 - -NOTES: - [07.02.2023] pzotov - Adjusted tail of restore log: added messages: - gbak: ERROR:Database is not online due to failure to activate one or more indices. - gbak: ERROR: Run gfix -online to bring database online without active indices. - (actual since 5.0.0.932; will be soon also for FB 3.x and 4.x - see letter from Alex, 07.02.2023 11:53). -""" - -import pytest -from pathlib import Path -from firebird.qa import * - -init_script = """ - create table test_1(x int); - create table test_2(x int); - insert into test_1 values(1); - insert into test_1 values(2); - insert into test_1 values(3); - commit; - create unique index test_1_unq on test_1 computed by( iif( exists(select * from test_2), 1, x ) ); - commit; - insert into test_2 values(1000); - commit; -""" - -db = db_factory(init=init_script) - -act = python_act('db') - -expected_stdout = """ - gbak: ERROR:attempt to store duplicate value (visible to active transactions) in unique index "TEST_1_UNQ" - gbak: ERROR: Problematic key value is ( = 1) -""" -# gbak: ERROR:Database is not online due to failure to activate one or more indices. -# gbak: ERROR: Run gfix -online to bring database online without active indices. - -fbk_file = temp_file('core_5201.fbk') -tmp_db_file = temp_file('tmp_core_5201.fdb') - -@pytest.mark.version('>=3.0') -def test_1(act: Action, fbk_file: Path, tmp_db_file: Path): - with act.connect_server() as srv: - srv.database.backup(database=act.db.db_path, backup=fbk_file) - assert srv.readlines() == [] - # - #act.expected_stderr = 'We expect error' - act.expected_stdout = expected_stdout - - act.gbak(switches=['-rep', '-v', str(fbk_file), str(tmp_db_file)], combine_output = True) - - #with act.connect_server() as srv: - # srv.database.restore(database=act.db.db_path, backup=fbk_file, flags=SrvRestoreFlag.REPLACE) - - # filter stdout - #act.stdout = '\n'.join([line for line in act.stdout.splitlines() if ' ERROR:' in line]) - #act.stdout = '\n'.join([line for line in act.stdout.splitlines() if ' ERROR:' in line]) - assert act.return_code == 2 - assert act.stdout == '' - #assert act.clean_stdout == act.clean_expected_stdout - From 75d3fa964cca140e0b23373e1abf929b29c040d0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 15 May 2024 10:41:40 +0300 Subject: [PATCH 0020/1064] Added/Updated tests\bugs\gh_8112_test.py: Checked on 6.0.0.351, 5.0.1.1399. --- tests/bugs/gh_8112_test.py | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/bugs/gh_8112_test.py diff --git a/tests/bugs/gh_8112_test.py b/tests/bugs/gh_8112_test.py new file mode 100644 index 00000000..53d49097 --- /dev/null +++ b/tests/bugs/gh_8112_test.py @@ -0,0 +1,45 @@ +#coding:utf-8 + +""" +ID: issue-8112 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8112 +TITLE: Error isc_read_only_trans (335544361) should report SQLSTATE 25006. +DESCRIPTION: +NOTES: + Confirmed problem on 6.0.0.345, 5.0.1.1395. + Checked on 6.0.0.351, 5.0.1.1399. +""" +import pytest +from firebird.qa import * +from firebird.driver import tpb, Isolation, TraLockResolution, TraAccessMode, DatabaseError + +init_sql = """ + recreate table test(id int default current_transaction); +""" +db = db_factory(init = init_sql) +act = python_act('db', substitutions = [('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0.1') +def test_1(act: Action, capsys): + + try: + custom_tpb = tpb(isolation = Isolation.SERIALIZABLE, access_mode = TraAccessMode.READ) + with act.db.connect() as con: + tx = con.transaction_manager(custom_tpb) + cur = tx.cursor() + cur.execute('insert into test default values') + con.commit() + + except DatabaseError as e: + print(e.sqlstate) # must be '25006' after fix. + print(e.__str__()) + for g in e.gds_codes: + print(g) + + act.expected_stdout = f""" + 25006 + attempted update during read-only transaction + 335544361 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From a70397a548031c18b18c4310eeb188af716b196f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 15 May 2024 17:41:47 +0300 Subject: [PATCH 0021/1064] Added/Updated tests\bugs\gh_8108_test.py: Checked on intermediate snapshots: 6.0.0.351 #02ef0c8, 5.0.1.1399 #5b8b57c, 4.0.5.3099 #bc1ad78 --- tests/bugs/gh_8108_test.py | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/bugs/gh_8108_test.py diff --git a/tests/bugs/gh_8108_test.py b/tests/bugs/gh_8108_test.py new file mode 100644 index 00000000..357aad93 --- /dev/null +++ b/tests/bugs/gh_8108_test.py @@ -0,0 +1,49 @@ +#coding:utf-8 + +""" +ID: issue-8108 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8108 +TITLE: Engine returns empty string when unable to translate Unicode symbol into ICU-codepage. +DESCRIPTION: +NOTES: + [15.05.2024] pzotov + Confirmed ticket notes on 4.0.5.3092: empty string is returned instead of error with SQLSTATE = 22018. + Checked on intermediate snapshots: 6.0.0.351 #02ef0c8, 5.0.1.1399 #5b8b57c, 4.0.5.3099 #bc1ad78 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + + -- Hangul Choseong Filler + -- x115F; + -- FB3 returns an error, FB4 OK (an error is expected) + select '>' || cast(_utf8 'ᅟ' as varchar(1) character set tis620) || '<' from rdb$database; + --select '>' || cast( cast(unicode_char(0x115f) as varchar(1) character set utf8) as varchar(1) character set tis620) || '<' from rdb$database; + + -- FB3 and FB4 return an error (it is OK) + select '>' || cast(_utf8 'ᅟ' as varchar(1) character set win1251) || '<' from rdb$database; + --select '>' || cast( cast(unicode_char(0x115f) as varchar(1) character set utf8) as varchar(1) character set win1251) || '<' from rdb$database; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + Statement failed, SQLSTATE = 22018 + arithmetic exception, numeric overflow, or string truncation + -Cannot transliterate character between character sets + + Statement failed, SQLSTATE = 22018 + arithmetic exception, numeric overflow, or string truncation + -Cannot transliterate character between character sets +""" + +@pytest.mark.version('>=4.0.5') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 40741bd449ed1a03a3010401d85590cee54648a9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 15 May 2024 20:26:01 +0300 Subject: [PATCH 0022/1064] Added 'pytest.mark.trace' to all tests which launch trace. Purpose: reduce time of QA run which started only to check whether trace session can cause pytest hang at the end of run. --- tests/bugs/core_2940_test.py | 1 + tests/bugs/core_2981_test.py | 1 + tests/bugs/core_3008_test.py | 1 + tests/bugs/core_3168_test.py | 1 + tests/bugs/core_3413_test.py | 1 + tests/bugs/core_3537_test.py | 1 + tests/bugs/core_3598_test.py | 1 + tests/bugs/core_3658_test.py | 1 + tests/bugs/core_3884_test.py | 1 + tests/bugs/core_3934_test.py | 1 + tests/bugs/core_4094_test.py | 1 + tests/bugs/core_4135_test.py | 1 + tests/bugs/core_4319_test.py | 2 + tests/bugs/core_4337_test.py | 1 + tests/bugs/core_4345_test.py | 1 + tests/bugs/core_4451_test.py | 1 + tests/bugs/core_4889_test.py | 1 + tests/bugs/core_4927_test.py | 1 + tests/bugs/core_5269_test.py | 1 + tests/bugs/core_5273_test.py | 4 +- tests/bugs/core_5330_test.py | 4 +- tests/bugs/core_5435_test.py | 1 + tests/bugs/core_5441_test.py | 1 + tests/bugs/core_5470_addi_test.py | 1 + tests/bugs/core_5470_test.py | 1 + tests/bugs/core_5475_test.py | 1 + tests/bugs/core_5477_test.py | 1 + tests/bugs/core_5488_session_idle_test.py | 1 + tests/bugs/core_5489_test.py | 1 + tests/bugs/core_5706_test.py | 1 + tests/bugs/core_5907_test.py | 1 + tests/bugs/core_5991_test.py | 1 + tests/bugs/core_5995_test.py | 1 + tests/bugs/core_6095_test.py | 1 + tests/bugs/core_6272_test.py | 1 + tests/bugs/core_6469_test.py | 1 + tests/bugs/gh_3106_test.py | 1 + tests/bugs/gh_6782_test.py | 1 + tests/bugs/gh_7139_test.py | 1 + tests/bugs/gh_7165_test.py | 1 + tests/bugs/gh_7208_test.py | 1 + tests/bugs/gh_7426_test.py | 1 + tests/bugs/gh_7466_plans_tracking_test.py | 1 + tests/bugs/gh_7466_test.py | 1 + tests/bugs/gh_7558_test.py | 1 + tests/bugs/test_trace_eol.py | 81 +++++++++++++++++++ tests/bugs/test_trace_eol_cr_space_nl.py | 81 +++++++++++++++++++ .../test_role_in_service_attachment.py | 1 + .../syspriv/test_trace_any_attachment.py | 1 + ...read_consist_statement_delete_undone_01.py | 1 + ...read_consist_statement_delete_undone_02.py | 1 + ...onsist_sttm_merge_deny_multiple_matches.py | 1 + ...est_read_consist_sttm_restart_max_limit.py | 1 + ..._read_consist_sttm_restart_on_delete_01.py | 1 + ..._read_consist_sttm_restart_on_delete_02.py | 1 + ..._read_consist_sttm_restart_on_delete_03.py | 1 + ..._read_consist_sttm_restart_on_delete_04.py | 1 + ...t_read_consist_sttm_restart_on_merge_01.py | 1 + ...t_read_consist_sttm_restart_on_merge_02.py | 1 + ...t_read_consist_sttm_restart_on_merge_03.py | 1 + ...t_read_consist_sttm_restart_on_merge_04.py | 1 + ..._read_consist_sttm_restart_on_update_01.py | 1 + ..._read_consist_sttm_restart_on_update_02.py | 1 + ..._read_consist_sttm_restart_on_update_03.py | 1 + ..._read_consist_sttm_restart_on_update_04.py | 1 + .../trigger/database/test_disconnect_05.py | 1 + .../trigger/database/test_disconnect_06.py | 1 + 67 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 tests/bugs/test_trace_eol.py create mode 100644 tests/bugs/test_trace_eol_cr_space_nl.py diff --git a/tests/bugs/core_2940_test.py b/tests/bugs/core_2940_test.py index 110f6521..b204ba4d 100644 --- a/tests/bugs/core_2940_test.py +++ b/tests/bugs/core_2940_test.py @@ -69,6 +69,7 @@ ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action): with act.trace(db_events=trace): diff --git a/tests/bugs/core_2981_test.py b/tests/bugs/core_2981_test.py index c8ad0936..fe0b2406 100644 --- a/tests/bugs/core_2981_test.py +++ b/tests/bugs/core_2981_test.py @@ -127,6 +127,7 @@ 'max_arg_count = 30', ] +@pytest.mark.trace @pytest.mark.version('>=3') def test_1(act: Action): # Get content of firebird.log BEFORE test diff --git a/tests/bugs/core_3008_test.py b/tests/bugs/core_3008_test.py index f78f1580..7d328982 100644 --- a/tests/bugs/core_3008_test.py +++ b/tests/bugs/core_3008_test.py @@ -28,6 +28,7 @@ 'time_threshold = 0', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action): with act.trace(db_events=trace): diff --git a/tests/bugs/core_3168_test.py b/tests/bugs/core_3168_test.py index 126fdc59..eee22ae4 100644 --- a/tests/bugs/core_3168_test.py +++ b/tests/bugs/core_3168_test.py @@ -29,6 +29,7 @@ temp_file = temp_file('test-file') +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, temp_file): with act.trace(svc_events=trace), act.connect_server() as srv: diff --git a/tests/bugs/core_3413_test.py b/tests/bugs/core_3413_test.py index fccab271..eb44ee6b 100644 --- a/tests/bugs/core_3413_test.py +++ b/tests/bugs/core_3413_test.py @@ -30,6 +30,7 @@ 'log_statement_finish = foo' ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action): with act.trace(db_events=trace): diff --git a/tests/bugs/core_3537_test.py b/tests/bugs/core_3537_test.py index d19f7f19..21d89384 100644 --- a/tests/bugs/core_3537_test.py +++ b/tests/bugs/core_3537_test.py @@ -136,6 +136,7 @@ 'log_initfini = false', ] +@pytest.mark.trace @pytest.mark.version('>=3') def test_1(act: Action, capsys): NUM_ROWS_TO_BE_ADDED = 45000 diff --git a/tests/bugs/core_3598_test.py b/tests/bugs/core_3598_test.py index c0648e8b..a1a32f89 100644 --- a/tests/bugs/core_3598_test.py +++ b/tests/bugs/core_3598_test.py @@ -83,6 +83,7 @@ 'log_initfini = false', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): expected_stdout = '' diff --git a/tests/bugs/core_3658_test.py b/tests/bugs/core_3658_test.py index 033aa60d..f6097e0d 100644 --- a/tests/bugs/core_3658_test.py +++ b/tests/bugs/core_3658_test.py @@ -41,6 +41,7 @@ 'log_errors = true', ] +@pytest.mark.trace @pytest.mark.version('>=3') def test_1(act: Action, tmp_trace_cfg: Path, tmp_trace_log: Path, capsys): #print( os.environ.get('ISC_USER', 'UNKNOWN_ISC_USR') ) diff --git a/tests/bugs/core_3884_test.py b/tests/bugs/core_3884_test.py index d25b6364..ae06320f 100644 --- a/tests/bugs/core_3884_test.py +++ b/tests/bugs/core_3884_test.py @@ -44,6 +44,7 @@ -At block line: 3, col: 13 """ +@pytest.mark.trace @pytest.mark.version('>=3') def test_1(act: Action, capsys): diff --git a/tests/bugs/core_3934_test.py b/tests/bugs/core_3934_test.py index 7f14f311..c7753d0a 100644 --- a/tests/bugs/core_3934_test.py +++ b/tests/bugs/core_3934_test.py @@ -38,6 +38,7 @@ def check_sweep(act: Action, log_sweep: bool): with act.trace(db_events=cfg), act.connect_server() as srv: srv.database.sweep(database=act.db.db_path) +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action): # Case 1 - sweep logged diff --git a/tests/bugs/core_4094_test.py b/tests/bugs/core_4094_test.py index 55f84143..9e9d014b 100644 --- a/tests/bugs/core_4094_test.py +++ b/tests/bugs/core_4094_test.py @@ -72,6 +72,7 @@ 'log_statement_start = true', ] +@pytest.mark.trace @pytest.mark.version('>=3') def test_1(act: Action, capsys): with act.trace(db_events=trace): diff --git a/tests/bugs/core_4135_test.py b/tests/bugs/core_4135_test.py index 7511d760..0a0b4f4f 100644 --- a/tests/bugs/core_4135_test.py +++ b/tests/bugs/core_4135_test.py @@ -66,6 +66,7 @@ 'log_trigger_finish = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): # How many rows must be inserted to the test table: diff --git a/tests/bugs/core_4319_test.py b/tests/bugs/core_4319_test.py index a29e4e5e..f8c228b9 100644 --- a/tests/bugs/core_4319_test.py +++ b/tests/bugs/core_4319_test.py @@ -52,6 +52,8 @@ """.split('\n') NO_SUCH_ALIAS = 'n0_$uch_f1le' + +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): diff --git a/tests/bugs/core_4337_test.py b/tests/bugs/core_4337_test.py index f2e382bc..964308d7 100644 --- a/tests/bugs/core_4337_test.py +++ b/tests/bugs/core_4337_test.py @@ -133,6 +133,7 @@ 'log_connections = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, sweep_log: Path, capsys): diff --git a/tests/bugs/core_4345_test.py b/tests/bugs/core_4345_test.py index e91a93ed..3a324582 100644 --- a/tests/bugs/core_4345_test.py +++ b/tests/bugs/core_4345_test.py @@ -74,6 +74,7 @@ 'log_function_finish = true' ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action): output = [] diff --git a/tests/bugs/core_4451_test.py b/tests/bugs/core_4451_test.py index 852e63bc..d3ab4a2b 100644 --- a/tests/bugs/core_4451_test.py +++ b/tests/bugs/core_4451_test.py @@ -34,6 +34,7 @@ 'include_filter=%(from|join)[[:whitespace:]]test%', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): with act.trace(db_events=trace): diff --git a/tests/bugs/core_4889_test.py b/tests/bugs/core_4889_test.py index 8cc7dfd0..c1d0d5bf 100644 --- a/tests/bugs/core_4889_test.py +++ b/tests/bugs/core_4889_test.py @@ -54,6 +54,7 @@ 'log_errors = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): with act.trace(db_events=trace): diff --git a/tests/bugs/core_4927_test.py b/tests/bugs/core_4927_test.py index 58a60437..d40e7173 100644 --- a/tests/bugs/core_4927_test.py +++ b/tests/bugs/core_4927_test.py @@ -99,6 +99,7 @@ 'print_perf = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): with act.trace(db_events=trace): diff --git a/tests/bugs/core_5269_test.py b/tests/bugs/core_5269_test.py index 1256aa86..e85839cc 100644 --- a/tests/bugs/core_5269_test.py +++ b/tests/bugs/core_5269_test.py @@ -61,6 +61,7 @@ where p.rdb$user = upper('TMP$C5269_2'); """ +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, user_a: User, user_b: User, test_role: Role): with act.db.connect() as con: diff --git a/tests/bugs/core_5273_test.py b/tests/bugs/core_5273_test.py index 8855229b..f51a59e7 100644 --- a/tests/bugs/core_5273_test.py +++ b/tests/bugs/core_5273_test.py @@ -3,8 +3,7 @@ """ ID: issue-5551 ISSUE: 5551 -TITLE: Crash when attempt to create database with running trace ( internal Firebird - consistency check (cannot find tip page (165), file: tra.cpp line: 2233) ) +TITLE: Attempt to create database with running trace leads to consistency check (cannot find tip page (165), file: tra.cpp line: 2233) DESCRIPTION: 1. Get the content of firebird.log before test. 2. Make config file and launch trace session, with separate logging of its STDOUT and STDERR. @@ -43,6 +42,7 @@ 'max_log_size = 5000000', ] +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, temp_db: Path): sql_ddl = f""" diff --git a/tests/bugs/core_5330_test.py b/tests/bugs/core_5330_test.py index d5c370ca..89a52ab1 100644 --- a/tests/bugs/core_5330_test.py +++ b/tests/bugs/core_5330_test.py @@ -3,8 +3,7 @@ """ ID: issue-5606 ISSUE: 5606 -TITLE: Trace session leads FB 4.0 to hang after 2nd launch of trivial .sql script. - Neither attach to any database nor regular restart of FB service can be done. +TITLE: Trace session leads FB 4.0 to hang after 2nd launch of trivial .sql script. Neither attach to any database nor regular restart of FB service can be done. DESCRIPTION: Ticket issue was reproduced on trivial trace config with single line ("enabled = true"). We prepare such config, launch trace session in async mode and run THREE times isql with logging its output. @@ -87,6 +86,7 @@ '}'] +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, capsys): with act.trace(config=trace, keep_log=False): diff --git a/tests/bugs/core_5435_test.py b/tests/bugs/core_5435_test.py index 88de6dff..e449df69 100644 --- a/tests/bugs/core_5435_test.py +++ b/tests/bugs/core_5435_test.py @@ -95,6 +95,7 @@ 'log_statement_finish = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0.2') def test_1(act: Action): act.isql(switches=[], input=async_init_script) diff --git a/tests/bugs/core_5441_test.py b/tests/bugs/core_5441_test.py index 88332365..7133e8e9 100644 --- a/tests/bugs/core_5441_test.py +++ b/tests/bugs/core_5441_test.py @@ -64,6 +64,7 @@ 'include_filter = "%(select % from test where x = ?)%"', ] +@pytest.mark.trace @pytest.mark.version('>=3.0.2') def test_1(act: Action, capsys): with act.trace(db_events=trace), act.db.connect() as con: diff --git a/tests/bugs/core_5470_addi_test.py b/tests/bugs/core_5470_addi_test.py index 1c12a711..78a4568c 100644 --- a/tests/bugs/core_5470_addi_test.py +++ b/tests/bugs/core_5470_addi_test.py @@ -77,6 +77,7 @@ expected_stdout_trace = test_sql.replace('set list on;', '').replace(';','') +@pytest.mark.trace @pytest.mark.version('>=3.0.6') @pytest.mark.platform('Windows') def test_1(act: Action, capsys): diff --git a/tests/bugs/core_5470_test.py b/tests/bugs/core_5470_test.py index 0c9012d3..7d611d3f 100644 --- a/tests/bugs/core_5470_test.py +++ b/tests/bugs/core_5470_test.py @@ -98,6 +98,7 @@ rdb$database /* ddl_3 line_8 */ """ +@pytest.mark.trace @pytest.mark.version('>=3.0.2') def test_1(act: Action, tmp_file: Path, capsys): with act.trace(db_events=trace), act.db.connect() as con: diff --git a/tests/bugs/core_5475_test.py b/tests/bugs/core_5475_test.py index fff8b6f7..f94e0387 100644 --- a/tests/bugs/core_5475_test.py +++ b/tests/bugs/core_5475_test.py @@ -107,6 +107,7 @@ # 2) 335544913 : value exceeds the range for valid timestamps ] +@pytest.mark.trace @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): with act.trace(db_events=trace): diff --git a/tests/bugs/core_5477_test.py b/tests/bugs/core_5477_test.py index 913ca35a..3c964d45 100644 --- a/tests/bugs/core_5477_test.py +++ b/tests/bugs/core_5477_test.py @@ -42,6 +42,7 @@ 'log_statement_finish = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0.2') @pytest.mark.platform('Windows') def test_1(act: Action, tmp_file: Path, capsys): diff --git a/tests/bugs/core_5488_session_idle_test.py b/tests/bugs/core_5488_session_idle_test.py index 997595e1..532fa0fd 100644 --- a/tests/bugs/core_5488_session_idle_test.py +++ b/tests/bugs/core_5488_session_idle_test.py @@ -86,6 +86,7 @@ 'log_statement_finish = true', ] +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, capsys): trace_dts_pattern = re.compile('.*(ATTACH_DATABASE|START_TRANSACTION|EXECUTE_STATEMENT_FINISH|ROLLBACK_TRANSACTION|DETACH_DATABASE)') diff --git a/tests/bugs/core_5489_test.py b/tests/bugs/core_5489_test.py index edeff15a..a1c845be 100644 --- a/tests/bugs/core_5489_test.py +++ b/tests/bugs/core_5489_test.py @@ -93,6 +93,7 @@ 'log_initfini = false', ] +@pytest.mark.trace @pytest.mark.version('>=3.0.2') def test_1(act: Action): diff --git a/tests/bugs/core_5706_test.py b/tests/bugs/core_5706_test.py index 620dc3c9..95889640 100644 --- a/tests/bugs/core_5706_test.py +++ b/tests/bugs/core_5706_test.py @@ -57,6 +57,7 @@ } """ +@pytest.mark.trace @pytest.mark.version('>=3.0.3') def test_1(act: Action): log_before = act.get_firebird_log() diff --git a/tests/bugs/core_5907_test.py b/tests/bugs/core_5907_test.py index 0fa2091f..e3f19380 100644 --- a/tests/bugs/core_5907_test.py +++ b/tests/bugs/core_5907_test.py @@ -42,6 +42,7 @@ '}' ] +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, capsys): with act.trace(config=trace_conf): diff --git a/tests/bugs/core_5991_test.py b/tests/bugs/core_5991_test.py index fc8719ca..19cf7836 100644 --- a/tests/bugs/core_5991_test.py +++ b/tests/bugs/core_5991_test.py @@ -95,6 +95,7 @@ '}' ] +@pytest.mark.trace @pytest.mark.version('>=3.0.5') def test_1(act: Action, capsys): trace.insert(0, f"database = '{act.db.db_path}'") diff --git a/tests/bugs/core_5995_test.py b/tests/bugs/core_5995_test.py index c157c1cb..af374076 100644 --- a/tests/bugs/core_5995_test.py +++ b/tests/bugs/core_5995_test.py @@ -25,6 +25,7 @@ 'log_statement_finish = true', ] +@pytest.mark.trace @pytest.mark.version('>=3.0.5') def test_1(act: Action): with act.trace(db_events=trace), act.connect_server() as srv: diff --git a/tests/bugs/core_6095_test.py b/tests/bugs/core_6095_test.py index c7f4282e..26a96220 100644 --- a/tests/bugs/core_6095_test.py +++ b/tests/bugs/core_6095_test.py @@ -61,6 +61,7 @@ ,re.compile('\\s*New\\s+number\\s+\\d+\\s*', re.IGNORECASE) ] +@pytest.mark.trace @pytest.mark.version('>=3.0.6') def test_1(act: Action, capsys): diff --git a/tests/bugs/core_6272_test.py b/tests/bugs/core_6272_test.py index 789dbff6..9ca82e35 100644 --- a/tests/bugs/core_6272_test.py +++ b/tests/bugs/core_6272_test.py @@ -63,6 +63,7 @@ trace_conf = temp_file('trace.conf') +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, db_nonexistent: Database, trace_conf: Path, capsys): with ServerKeeper(act, None): # Use embedded server for trace diff --git a/tests/bugs/core_6469_test.py b/tests/bugs/core_6469_test.py index 13977076..20d75618 100644 --- a/tests/bugs/core_6469_test.py +++ b/tests/bugs/core_6469_test.py @@ -184,6 +184,7 @@ def run_script(act: Action, tmp_file: Path): act.isql(switches=['-n', '-q'], input_file = tmp_file, connect_db = False, credentials = False) +@pytest.mark.trace @pytest.mark.version('>=4.0') @pytest.mark.platform('Windows') def test_1(act: Action, test_role: Role, tmp_file: Path, capsys): diff --git a/tests/bugs/gh_3106_test.py b/tests/bugs/gh_3106_test.py index 624c2eac..77810f46 100644 --- a/tests/bugs/gh_3106_test.py +++ b/tests/bugs/gh_3106_test.py @@ -61,6 +61,7 @@ """ +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, capsys): trace_cfg_items = [ diff --git a/tests/bugs/gh_6782_test.py b/tests/bugs/gh_6782_test.py index 976a40de..cc7921e6 100644 --- a/tests/bugs/gh_6782_test.py +++ b/tests/bugs/gh_6782_test.py @@ -167,6 +167,7 @@ FOUND line with execution statistics """ +@pytest.mark.trace @pytest.mark.version('>=3.0.8') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7139_test.py b/tests/bugs/gh_7139_test.py index 40d5fa78..f77564f0 100644 --- a/tests/bugs/gh_7139_test.py +++ b/tests/bugs/gh_7139_test.py @@ -65,6 +65,7 @@ def get_external_trace_id(act: Action, a_what_to_check, a_ext_trace_session_name #------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, tmp_trace_cfg: Path, tmp_trace_log: Path, capsys): diff --git a/tests/bugs/gh_7165_test.py b/tests/bugs/gh_7165_test.py index 6f403737..2624576a 100644 --- a/tests/bugs/gh_7165_test.py +++ b/tests/bugs/gh_7165_test.py @@ -53,6 +53,7 @@ Missing security context for TEST.FDB """ +@pytest.mark.trace @pytest.mark.version('>=5.0') @pytest.mark.platform('Windows') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7208_test.py b/tests/bugs/gh_7208_test.py index b91a8377..534ff933 100644 --- a/tests/bugs/gh_7208_test.py +++ b/tests/bugs/gh_7208_test.py @@ -271,6 +271,7 @@ 0 records fetched """ +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7426_test.py b/tests/bugs/gh_7426_test.py index e073a9eb..c4338dbe 100644 --- a/tests/bugs/gh_7426_test.py +++ b/tests/bugs/gh_7426_test.py @@ -41,6 +41,7 @@ allowed_patterns = [ ' ERROR AT ', 'Trigger TRG_ANY_DDL_STATEMENT_', ] allowed_patterns = [ re.compile(r, re.IGNORECASE) for r in allowed_patterns] +@pytest.mark.trace @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7466_plans_tracking_test.py b/tests/bugs/gh_7466_plans_tracking_test.py index 46d9a830..a745649c 100644 --- a/tests/bugs/gh_7466_plans_tracking_test.py +++ b/tests/bugs/gh_7466_plans_tracking_test.py @@ -73,6 +73,7 @@ def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped +@pytest.mark.trace @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7466_test.py b/tests/bugs/gh_7466_test.py index 641a788d..df8b51a2 100644 --- a/tests/bugs/gh_7466_test.py +++ b/tests/bugs/gh_7466_test.py @@ -64,6 +64,7 @@ allowed_patterns = [ ' ERROR AT ', 'Trigger TRG_', 'Procedure (SP_TEST|PG_TEST.PG_SP_WORKER)', 'Function (FN_TEST|PG_TEST.PG_FN_WORKER)' ] allowed_patterns = [ re.compile(r, re.IGNORECASE) for r in allowed_patterns] +@pytest.mark.trace @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7558_test.py b/tests/bugs/gh_7558_test.py index 219e1376..ca790c37 100644 --- a/tests/bugs/gh_7558_test.py +++ b/tests/bugs/gh_7558_test.py @@ -35,6 +35,7 @@ act = python_act('db', substitutions = substitutions) act_non_existing_database = python_act('db_non_existing_database') +@pytest.mark.trace @pytest.mark.version('>=4.0.3') def test_1(act: Action, act_non_existing_database: Action, tmp_user: User, tmp_role: Role, tmp_usr2: User, capsys): diff --git a/tests/bugs/test_trace_eol.py b/tests/bugs/test_trace_eol.py new file mode 100644 index 00000000..5d83e4c1 --- /dev/null +++ b/tests/bugs/test_trace_eol.py @@ -0,0 +1,81 @@ +#coding:utf-8 + +""" +ID: issue-5740-A +ISSUE: 5740-A +TITLE: Trace INCLUDE_FILTER with [[:WHITESPACE:]]+ does not work when statement contains newline is issued +DESCRIPTION: + We create a list of several DDLs which all contain NEWLINE character(s) between keyword and name of DB object. + Then we launch trace session and execute all these DDLs. + Finally we check whether trace log contains every DDL or not. + Expected result: text of every DDL should be FOUND in the trace log. +JIRA: CORE-5470 +FBTEST: bugs.core_5470 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +act = python_act('db') + +ddl_lst = ["""recreate /* ddl_1 line_1 */ + + table /* ddl_1 line_2 */ + + + + t_test /* ddl_1 line_3 */ (x int) + """, + """comment on /* ddl_2 line_1 */ + table /* ddl_2 line_2 */ + + + t_test is /* ddl_2 line_3 */ + 'foo /* ddl_2 line_4 */ + /* ddl_2 line_4 */ bar' + """, +""" + + create /* ddl_3 line_1 */ + or /* ddl_3 line_2 */ + + alter /* ddl_3 line_3 */ + view /* ddl_3 line_4 */ + + v_rio /* ddl_3 line_5 */ + + as /* ddl_3 line_6 */ + select * /* ddl_3 line_6 */ + from /* ddl_3 line_7 */ + + rdb$database /* ddl_3 line_8 */ + """] + +trace = ['time_threshold = 0', + 'log_initfini = false', + 'log_errors = true', + 'log_statement_finish = true', + #'include_filter = "%(recreate|create|alter|drop|comment on)[[:WHITESPACE:]]+(domain|generator|sequence|exception|procedure|function|table|index|view|trigger|role|filter|external function)%"', + 'include_filter = "%(ddl_[[:DIGIT:]]+[[:WHITESPACE:]]+line_[[:DIGIT:]]+)%"', + ] + +@pytest.mark.trace +@pytest.mark.version('>=3') +def test_1(act: Action, capsys): + with act.trace(db_events=trace), act.db.connect() as con: + for cmd in ddl_lst: + con.execute_immediate(cmd) + con.commit() + + #print(act.trace_to_stdout()) + print(act.trace_log) + act.expected_stdout = '' # expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + + # Check + #act.trace_to_stdout() + #for cmd in ddl_lst: + # assert act.stdout.find(cmd) > 0 diff --git a/tests/bugs/test_trace_eol_cr_space_nl.py b/tests/bugs/test_trace_eol_cr_space_nl.py new file mode 100644 index 00000000..5d83e4c1 --- /dev/null +++ b/tests/bugs/test_trace_eol_cr_space_nl.py @@ -0,0 +1,81 @@ +#coding:utf-8 + +""" +ID: issue-5740-A +ISSUE: 5740-A +TITLE: Trace INCLUDE_FILTER with [[:WHITESPACE:]]+ does not work when statement contains newline is issued +DESCRIPTION: + We create a list of several DDLs which all contain NEWLINE character(s) between keyword and name of DB object. + Then we launch trace session and execute all these DDLs. + Finally we check whether trace log contains every DDL or not. + Expected result: text of every DDL should be FOUND in the trace log. +JIRA: CORE-5470 +FBTEST: bugs.core_5470 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +act = python_act('db') + +ddl_lst = ["""recreate /* ddl_1 line_1 */ + + table /* ddl_1 line_2 */ + + + + t_test /* ddl_1 line_3 */ (x int) + """, + """comment on /* ddl_2 line_1 */ + table /* ddl_2 line_2 */ + + + t_test is /* ddl_2 line_3 */ + 'foo /* ddl_2 line_4 */ + /* ddl_2 line_4 */ bar' + """, +""" + + create /* ddl_3 line_1 */ + or /* ddl_3 line_2 */ + + alter /* ddl_3 line_3 */ + view /* ddl_3 line_4 */ + + v_rio /* ddl_3 line_5 */ + + as /* ddl_3 line_6 */ + select * /* ddl_3 line_6 */ + from /* ddl_3 line_7 */ + + rdb$database /* ddl_3 line_8 */ + """] + +trace = ['time_threshold = 0', + 'log_initfini = false', + 'log_errors = true', + 'log_statement_finish = true', + #'include_filter = "%(recreate|create|alter|drop|comment on)[[:WHITESPACE:]]+(domain|generator|sequence|exception|procedure|function|table|index|view|trigger|role|filter|external function)%"', + 'include_filter = "%(ddl_[[:DIGIT:]]+[[:WHITESPACE:]]+line_[[:DIGIT:]]+)%"', + ] + +@pytest.mark.trace +@pytest.mark.version('>=3') +def test_1(act: Action, capsys): + with act.trace(db_events=trace), act.db.connect() as con: + for cmd in ddl_lst: + con.execute_immediate(cmd) + con.commit() + + #print(act.trace_to_stdout()) + print(act.trace_log) + act.expected_stdout = '' # expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + + # Check + #act.trace_to_stdout() + #for cmd in ddl_lst: + # assert act.stdout.find(cmd) > 0 diff --git a/tests/functional/services/test_role_in_service_attachment.py b/tests/functional/services/test_role_in_service_attachment.py index 11d72181..ab9dee3f 100644 --- a/tests/functional/services/test_role_in_service_attachment.py +++ b/tests/functional/services/test_role_in_service_attachment.py @@ -43,6 +43,7 @@ #expected_stdout = 'SUCCESS: found expected line format in the trace log: :' +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, tmp_user: User, tmp_role:Role, tmp_trace_cfg: Path, tmp_trace_log: Path, capsys): diff --git a/tests/functional/syspriv/test_trace_any_attachment.py b/tests/functional/syspriv/test_trace_any_attachment.py index 77a74b8e..bcb43483 100644 --- a/tests/functional/syspriv/test_trace_any_attachment.py +++ b/tests/functional/syspriv/test_trace_any_attachment.py @@ -29,6 +29,7 @@ act = python_act('db') +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, tmp_user: User, tmp_role: Role, tmp_usr2: User, capsys): diff --git a/tests/functional/transactions/test_read_consist_statement_delete_undone_01.py b/tests/functional/transactions/test_read_consist_statement_delete_undone_01.py index 72acd756..e657b745 100644 --- a/tests/functional/transactions/test_read_consist_statement_delete_undone_01.py +++ b/tests/functional/transactions/test_read_consist_statement_delete_undone_01.py @@ -213,6 +213,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.3') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py b/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py index 2bd7ec7a..75dc97ce 100644 --- a/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py +++ b/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py @@ -203,6 +203,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.3') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py b/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py index e439284e..2aa275ea 100644 --- a/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py +++ b/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py @@ -172,6 +172,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_max_limit.py b/tests/functional/transactions/test_read_consist_sttm_restart_max_limit.py index d441b563..9b4bad40 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_max_limit.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_max_limit.py @@ -166,6 +166,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_01.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_01.py index 68da7f96..91bdb750 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_01.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_01.py @@ -234,6 +234,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_02.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_02.py index 3cadea0d..12b21601 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_02.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_02.py @@ -224,6 +224,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_03.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_03.py index f3bef90e..8025706b 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_03.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_03.py @@ -244,6 +244,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_04.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_04.py index f6f1c217..45a4e504 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_04.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_delete_04.py @@ -225,6 +225,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py index dbdb5cf2..9f021352 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py @@ -216,6 +216,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_02.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_02.py index 5e737b29..e04d8c23 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_02.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_02.py @@ -270,6 +270,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_03.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_03.py index ea2dd34c..070c96b6 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_03.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_03.py @@ -216,6 +216,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_04.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_04.py index 5cf6736c..d6be7be4 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_04.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_04.py @@ -238,6 +238,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_01.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_01.py index 52d6eab6..db931d0d 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_01.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_01.py @@ -216,6 +216,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_02.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_02.py index 1f4096c0..071519ba 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_02.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_02.py @@ -221,6 +221,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py index 8763a9fb..418877a0 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py @@ -225,6 +225,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0.2') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_04.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_04.py index ea6c94bf..1b9918a6 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_04.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_04.py @@ -223,6 +223,7 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec #----------------------------------------------------------------------------------------------------------------------------------------------------- +@pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: Path, capsys): sql_init = (act.files_dir / 'read-consist-sttm-restart-DDL.sql').read_text() diff --git a/tests/functional/trigger/database/test_disconnect_05.py b/tests/functional/trigger/database/test_disconnect_05.py index 2f44e11d..8a54dae4 100644 --- a/tests/functional/trigger/database/test_disconnect_05.py +++ b/tests/functional/trigger/database/test_disconnect_05.py @@ -71,6 +71,7 @@ act = python_act('db', substitutions = substitutions) +@pytest.mark.trace @pytest.mark.version('>=5.0') def test_1(act: Action, tmp_worker: User, capsys): diff --git a/tests/functional/trigger/database/test_disconnect_06.py b/tests/functional/trigger/database/test_disconnect_06.py index 4b439761..b59368c0 100644 --- a/tests/functional/trigger/database/test_disconnect_06.py +++ b/tests/functional/trigger/database/test_disconnect_06.py @@ -44,6 +44,7 @@ act = python_act('db', substitutions = substitutions) +@pytest.mark.trace @pytest.mark.version('>=5.0') def test_1(act: Action, tmp_worker: User, capsys): From e81c893c805cc396df203d2093512dcd79913a2f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 May 2024 11:33:08 +0300 Subject: [PATCH 0023/1064] Added custom marker 'trace' in order to avoid warnings --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index 3c98979a..04a3cfd4 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,6 +3,7 @@ console_output_style = count # testpaths = tests # addopts = --server local --install-terminal markers = + trace: mark a test as dealing with trace encryption: mark a test as dealing with encryption plugin replication: mark a test as dealing with database participating in replication disabled_in_forks: mark a test which must be SKIPPED when running QA against any FB forks (because of missed fix/feature etc). \ No newline at end of file From 1bc5ae63802e8ec8493072c4732dcda23b2fc49b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 May 2024 12:18:04 +0300 Subject: [PATCH 0024/1064] Added/Updated tests\bugs\test_trace_eol.py: fixed wrong code --- tests/bugs/test_trace_eol.py | 61 ++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/tests/bugs/test_trace_eol.py b/tests/bugs/test_trace_eol.py index 5d83e4c1..d9b1136f 100644 --- a/tests/bugs/test_trace_eol.py +++ b/tests/bugs/test_trace_eol.py @@ -1,14 +1,14 @@ #coding:utf-8 """ -ID: issue-5740-A -ISSUE: 5740-A +ID: issue-5740 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5740 TITLE: Trace INCLUDE_FILTER with [[:WHITESPACE:]]+ does not work when statement contains newline is issued DESCRIPTION: - We create a list of several DDLs which all contain NEWLINE character(s) between keyword and name of DB object. - Then we launch trace session and execute all these DDLs. - Finally we check whether trace log contains every DDL or not. - Expected result: text of every DDL should be FOUND in the trace log. + We create a list of several DDLs which all contain NEWLINE character(s) between keyword and name of DB object. + Then we launch trace session and execute all these DDLs. + Finally we check whether trace log contains every DDL or not. + Expected result: text of every DDL should be FOUND in the trace log. JIRA: CORE-5470 FBTEST: bugs.core_5470 """ @@ -20,7 +20,7 @@ act = python_act('db') -ddl_lst = ["""recreate /* ddl_1 line_1 */ +chk_statements_lst = ["""recreate /* ddl_1 line_1 */ table /* ddl_1 line_2 */ @@ -57,25 +57,52 @@ 'log_initfini = false', 'log_errors = true', 'log_statement_finish = true', - #'include_filter = "%(recreate|create|alter|drop|comment on)[[:WHITESPACE:]]+(domain|generator|sequence|exception|procedure|function|table|index|view|trigger|role|filter|external function)%"', + 'max_sql_length = 65500', 'include_filter = "%(ddl_[[:DIGIT:]]+[[:WHITESPACE:]]+line_[[:DIGIT:]]+)%"', ] @pytest.mark.trace -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0.2') def test_1(act: Action, capsys): with act.trace(db_events=trace), act.db.connect() as con: - for cmd in ddl_lst: + for cmd in chk_statements_lst: con.execute_immediate(cmd) con.commit() - #print(act.trace_to_stdout()) - print(act.trace_log) + trace_txt = '\n'.join( [line.rstrip() for line in act.trace_log] ) + missed_cnt = 0 + for sttm in [c.rstrip() for c in chk_statements_lst]: + if trace_txt.find(sttm) < 0: + missed_cnt += 1 + if missed_cnt == 1: + print('Missed in the trace log:') + + print('----- sttm start -----') + for x in [x.strip() for x in sttm.split('\n')]: + print(x) + print('----- sttm finish ----') + + if missed_cnt: + print('----- trace start -----') + for x in trace_txt.split('\n'): + print(x) + print('----- trace finish ----') + + + ''' + all_found = True + act.trace_to_stdout() + for cmd in chk_statements_lst: + #if act.stdout.find(cmd) <= 0: + # all_found = False + # print(f'{cmd=}') + # print(f'{act.stdout=}') + # print(f'{act.trace_log=}') + # break + # assert act.stdout.find(cmd) > 0 + print(f'{all_found=}') + ''' + act.expected_stdout = '' # expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout - - # Check - #act.trace_to_stdout() - #for cmd in ddl_lst: - # assert act.stdout.find(cmd) > 0 From c5b8c8834416c594cda4d3971296803b5e7e40fd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 May 2024 12:45:52 +0300 Subject: [PATCH 0025/1064] Added/Updated tests\bugs\test_trace_eol.py: added comments --- tests/bugs/test_trace_eol.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/tests/bugs/test_trace_eol.py b/tests/bugs/test_trace_eol.py index d9b1136f..45d174d9 100644 --- a/tests/bugs/test_trace_eol.py +++ b/tests/bugs/test_trace_eol.py @@ -10,7 +10,17 @@ Finally we check whether trace log contains every DDL or not. Expected result: text of every DDL should be FOUND in the trace log. JIRA: CORE-5470 -FBTEST: bugs.core_5470 +NOTES: + On Windows print(act.trace_log) displays text with EOL containing space between CR and LF, i.e.: chr(13) + space + chr(10): + ['2024-05-16T12:42:17.8040 ... EXECUTE_STATEMENT_FINISH\r \n', '\tE:\\TEMP\\QA\\FBQA\\TEST_10\\TEST.FDB ... :::1/62705)\r \n', ] + + Space between CR and LF likely is an artifact of list to string conversion done by print() using it's __str__ method. + Explanation see in reply from pcisar: + subj: "act.trace_log ends with strange EOL that is: CR + space + NL // Windows"; date: 05-MAR-2023 + In order to get trace text with normal EOLs we have to do: + trace_txt = '\n'.join( [line.rstrip() for line in act.trace_log] ) + + Confirmed bug on 4.0.0.483 (date of build: 05-jan-2017). """ import pytest @@ -88,21 +98,6 @@ def test_1(act: Action, capsys): print(x) print('----- trace finish ----') - - ''' - all_found = True - act.trace_to_stdout() - for cmd in chk_statements_lst: - #if act.stdout.find(cmd) <= 0: - # all_found = False - # print(f'{cmd=}') - # print(f'{act.stdout=}') - # print(f'{act.trace_log=}') - # break - # assert act.stdout.find(cmd) > 0 - print(f'{all_found=}') - ''' - - act.expected_stdout = '' # expected_stdout + act.expected_stdout = '' act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From b471dd71f4fd77884fc63e1ee630b71fbe1b30ba Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 May 2024 12:48:36 +0300 Subject: [PATCH 0026/1064] Renamed file because there was created appropriate ticket for it --- tests/bugs/{test_trace_eol.py => gh_5740_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/bugs/{test_trace_eol.py => gh_5740_test.py} (100%) diff --git a/tests/bugs/test_trace_eol.py b/tests/bugs/gh_5740_test.py similarity index 100% rename from tests/bugs/test_trace_eol.py rename to tests/bugs/gh_5740_test.py From 4947affe4a5f7a2408c6c6327008798def79d130 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 May 2024 12:49:49 +0300 Subject: [PATCH 0027/1064] Removed test that duplicated gh_5740_test.py --- tests/bugs/test_trace_eol_cr_space_nl.py | 81 ------------------------ 1 file changed, 81 deletions(-) delete mode 100644 tests/bugs/test_trace_eol_cr_space_nl.py diff --git a/tests/bugs/test_trace_eol_cr_space_nl.py b/tests/bugs/test_trace_eol_cr_space_nl.py deleted file mode 100644 index 5d83e4c1..00000000 --- a/tests/bugs/test_trace_eol_cr_space_nl.py +++ /dev/null @@ -1,81 +0,0 @@ -#coding:utf-8 - -""" -ID: issue-5740-A -ISSUE: 5740-A -TITLE: Trace INCLUDE_FILTER with [[:WHITESPACE:]]+ does not work when statement contains newline is issued -DESCRIPTION: - We create a list of several DDLs which all contain NEWLINE character(s) between keyword and name of DB object. - Then we launch trace session and execute all these DDLs. - Finally we check whether trace log contains every DDL or not. - Expected result: text of every DDL should be FOUND in the trace log. -JIRA: CORE-5470 -FBTEST: bugs.core_5470 -""" - -import pytest -from firebird.qa import * - -db = db_factory() - -act = python_act('db') - -ddl_lst = ["""recreate /* ddl_1 line_1 */ - - table /* ddl_1 line_2 */ - - - - t_test /* ddl_1 line_3 */ (x int) - """, - """comment on /* ddl_2 line_1 */ - table /* ddl_2 line_2 */ - - - t_test is /* ddl_2 line_3 */ - 'foo /* ddl_2 line_4 */ - /* ddl_2 line_4 */ bar' - """, -""" - - create /* ddl_3 line_1 */ - or /* ddl_3 line_2 */ - - alter /* ddl_3 line_3 */ - view /* ddl_3 line_4 */ - - v_rio /* ddl_3 line_5 */ - - as /* ddl_3 line_6 */ - select * /* ddl_3 line_6 */ - from /* ddl_3 line_7 */ - - rdb$database /* ddl_3 line_8 */ - """] - -trace = ['time_threshold = 0', - 'log_initfini = false', - 'log_errors = true', - 'log_statement_finish = true', - #'include_filter = "%(recreate|create|alter|drop|comment on)[[:WHITESPACE:]]+(domain|generator|sequence|exception|procedure|function|table|index|view|trigger|role|filter|external function)%"', - 'include_filter = "%(ddl_[[:DIGIT:]]+[[:WHITESPACE:]]+line_[[:DIGIT:]]+)%"', - ] - -@pytest.mark.trace -@pytest.mark.version('>=3') -def test_1(act: Action, capsys): - with act.trace(db_events=trace), act.db.connect() as con: - for cmd in ddl_lst: - con.execute_immediate(cmd) - con.commit() - - #print(act.trace_to_stdout()) - print(act.trace_log) - act.expected_stdout = '' # expected_stdout - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - - # Check - #act.trace_to_stdout() - #for cmd in ddl_lst: - # assert act.stdout.find(cmd) > 0 From b68ec5fd87a3a485cbe1ecbe42c532215bdd68c8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 May 2024 13:54:44 +0300 Subject: [PATCH 0028/1064] Added/Updated tests\bugs\gh_6609_test.py: Confirmed bug on 3.0.7.33348. Checked on 3.0.7.33350, 4.0.5.3099, 5.0.1.1399, 6.0.0.351. --- tests/bugs/gh_6609_test.py | 84 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/bugs/gh_6609_test.py diff --git a/tests/bugs/gh_6609_test.py b/tests/bugs/gh_6609_test.py new file mode 100644 index 00000000..57f296ca --- /dev/null +++ b/tests/bugs/gh_6609_test.py @@ -0,0 +1,84 @@ +#coding:utf-8 + +""" +ID: issue-6609 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6609 +TITLE: Memory leak at server, when client select computed field, which used COALESCE or CAST [CORE6370] +DESCRIPTION: + Problem can be seen if we run query to mon$memory_usage before and after loop with statement described in the ticket. + It is important that on every iteration of loop cursor will be re-created and closed after statement execution (see 'cur2'). + Ratio between values of mon$memory_usage was about 1.63 (for CS) and 1.26 (for SS) before fix. + After fix these values reduced to ~1.00 (for 3.x and 4.x), but for 5.x+ CS it is about 1.10. + NOTE: for Classic we have to compare mon$memory_usage that corresponds to ATTACHMENT level (see 'MON_QUERY' variable). +NOTES: + [18.05.2024] pzotov + Confirmed bug on 3.0.7.33348 (17-JUL-2020), mon$memo_used ratio for CS: 1.63; SS: 1.26 + Checked on: + 3.0.7.33350, mon$memo_used ratio for CS: 1.01; SS: 1.00 + 4.0.5.3099, mon$memo_used ratio for CS: 1.01; SS: 1.00 + 5.0.1.1399, mon$memo_used ratio for CS: 1.11; SS: 1.02 + 6.0.0.351, mon$memo_used ratio for CS: 1.11; SS: 1.02 +""" + +import pytest +import platform +from firebird.qa import * + +N_CNT = 30000 + +init_ddl = """ + recreate table tab1 ( + a1 varchar(99), + a2 varchar(199), + a3 computed by (coalesce(a1, '')||'-'||coalesce(a2, '')) + ); +""" + +db = db_factory(init = init_ddl) +act = python_act('db') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, capsys): + + #if act.platform == 'Windows': + # pytest.skip('Could not reproduce bug on Windows') + + if act.get_server_architecture() == 'SuperServer': + MON_QUERY = 'select mon$memory_used from mon$memory_usage where mon$stat_group = 0' + MAX_THRESHOLD = 1.10 + else: + MON_QUERY = """ + select m.mon$memory_used + from mon$attachments a + join mon$memory_usage m on a.mon$stat_id = m.mon$stat_id + where a.mon$attachment_id = current_connection and m.mon$stat_group = 1; + """ + MAX_THRESHOLD = 1.20 + + mon_memo_beg = 1 + mon_memo_end = 9999999 + with act.db.connect() as con: + cur = con.cursor() + cur.execute(MON_QUERY) + mon_memo_beg = int(cur.fetchone()[0]) + con.commit() + + for i in range(N_CNT): + cur2 = con.cursor() + cur2.execute(f"select /* iter {i+1} */ t.a3 from tab1 t") + for r in cur2: + pass + cur2.close() + + con.commit() + cur.execute(MON_QUERY) + mon_memo_end = int(cur.fetchone()[0]) + + msg_ok = 'Memory usage: EXPECTED' + if mon_memo_end / mon_memo_beg <= MAX_THRESHOLD: + print(msg_ok) + else: + print(f'Memory usage UNEXPECTED: {mon_memo_end} / {mon_memo_beg} = {mon_memo_end / mon_memo_beg:.2f} - greater than {MAX_THRESHOLD=}') + act.expected_stdout = msg_ok + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From d8ff4186da02af9df150b1199822338a6db7df82 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 May 2024 13:56:52 +0300 Subject: [PATCH 0029/1064] Added/Updated tests\bugs\gh_6609_test.py: Added comment. --- tests/bugs/gh_6609_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_6609_test.py b/tests/bugs/gh_6609_test.py index 57f296ca..1c9fa40f 100644 --- a/tests/bugs/gh_6609_test.py +++ b/tests/bugs/gh_6609_test.py @@ -13,6 +13,7 @@ NOTES: [18.05.2024] pzotov Confirmed bug on 3.0.7.33348 (17-JUL-2020), mon$memo_used ratio for CS: 1.63; SS: 1.26 + Bug was fixed in: dde597e6ae8bbaac45df4f8b38faa9583cd946d4 (27-JUL-2020). Checked on: 3.0.7.33350, mon$memo_used ratio for CS: 1.01; SS: 1.00 4.0.5.3099, mon$memo_used ratio for CS: 1.01; SS: 1.00 From 84cd024f1d869459a9a48b54b2fd7160b9c5082b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 20 May 2024 11:51:30 +0300 Subject: [PATCH 0030/1064] Added/Updated tests\bugs\gh_4723_test.py: Checked on 5.0.1.1399, 6.0.0.351 --- tests/bugs/gh_4723_test.py | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/bugs/gh_4723_test.py diff --git a/tests/bugs/gh_4723_test.py b/tests/bugs/gh_4723_test.py new file mode 100644 index 00000000..1d7ddda2 --- /dev/null +++ b/tests/bugs/gh_4723_test.py @@ -0,0 +1,112 @@ +#coding:utf-8 + +""" +ID: issue-4723 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/4723 +TITLE: Optimize the record-level RLE algorithm for a denser compression of shorter-than-declared strings and sets of subsequent NULLs [CORE4401] +DESCRIPTION: + Test creates table with nullable varchar column an adds lot of rows with NULL value. + Then we run gstat in order to parse statistics related to data pages and avg fill ratio. + gstat reports for data pages and avg ratio following values: + 4.0.5.3099: + Pointer pages: 2, data page slots: 2144 + Data pages: 2144, average fill: 91% + 5.0.1.1399, 6.0.0.351: + Pointer pages: 1, data page slots: 208 + Data pages: 208, average fill: 46% + Test assumes that values returned for 5.x will not be change in too wide range for several upcoming years + in any order - see MIN_* and MAX_* thresholds. +NOTES: + [20.05.2024] pzotov + Improvement URL (27-sep-2022 15:16): + https://github.com/FirebirdSQL/firebird/commit/54f1990b98d3e510a10d06fe9ceb76456804da52 + Improved record compression (denser encoding of repeating bytes and less blocks) (#7302) + + NB: snapshots that were just before and after this commit CAN NOT be verified: + 5.0.0.745: raised BUGCHECK ("decompression overran buffer (179), file: sqz.cpp line: 293") + 5.0.0.756: crashed + Checked on 5.0.1.1399, 6.0.0.351 for DB with page_size = 8192. +""" +import re + +import pytest +import platform +from firebird.qa import * + +N_ROWS = 30000 +N_WIDT = 32760 + +MIN_DP_COUNT_THRESHOLD = 190 +MAX_DP_COUNT_THRESHOLD = 230 +MIN_AVG_FILL_THRESHOLD = 30 +MAX_AVG_FILL_THRESHOLD = 60 + +init_ddl = f""" + recreate table test (f01 varchar({N_WIDT})); + commit; + + set term ^; + execute block as + declare n int = {N_ROWS}; + begin + while (n > 0) do + begin + insert into test(f01) values(null); + n = n - 1; + end + end + ^ + set term ;^ + commit; +""" + +db = db_factory(page_size = 8192, init = init_ddl) +act = python_act('db') + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + act.gstat(switches=['-d','-t', 'TEST', '-user', act.db.user, '-pass', act.db.password]) + + # 4.x: Pointer pages: 2, data page slots: 2144 + # 5.x: Pointer pages: 1, data page slots: 208 + p_pointer_pages_data_pages_slots = re.compile( r'Pointer\s+pages(:)?\s+\d+(,)?\s+data\s+page\s+slots(:)?\s+\d+' ) + + # Data pages: 208, average fill: 46% + p_data_pages_average_fill_ratio = re.compile( r'Data\s+pages(:)?\s+\d+(,)?\s+average\s+fill(:)?\s+\d+%' ) + + data_pages_cnt = avg_fill_ratio = -1 + gstat_lines = act.stdout.splitlines() + for line in gstat_lines: + #print(line) + if p_pointer_pages_data_pages_slots.search(line): + data_pages_cnt = int(line.split()[-1]) + if p_data_pages_average_fill_ratio.search(line): + avg_fill_ratio = int(line.split()[-1].replace('%','')) + + + data_pages_cnt_expected_msg = f'data_pages_cnt: expected, within {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}' + avg_fill_ratio_expected_msg = f'avg_fill_ratio: expected, within {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}' + if data_pages_cnt > 0 and avg_fill_ratio > 0: + if data_pages_cnt >= MIN_DP_COUNT_THRESHOLD and data_pages_cnt <= MAX_DP_COUNT_THRESHOLD: + print(data_pages_cnt_expected_msg) + else: + print(f'data_pages_cnt UNEXPECTED: {data_pages_cnt=} -- out of scope: {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}') + + if avg_fill_ratio >= MIN_AVG_FILL_THRESHOLD and avg_fill_ratio <= MAX_AVG_FILL_THRESHOLD: + print(avg_fill_ratio_expected_msg) + else: + print(f'avg_fill_ratio UNEXPECTED: {avg_fill_ratio=} -- out of scope: {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}') + else: + print(f'ERROR: at least one of: {data_pages_cnt=}, {avg_fill_ratio=} is INVALID.') + print('Could not properly parse gstat output:') + for p in gstat_lines: + print(p) + + act.expected_stdout = f""" + {data_pages_cnt_expected_msg} + {avg_fill_ratio_expected_msg} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From 3ee4a2f95a8cb40b81dd6e99905451b9e8f1a38f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 20 May 2024 13:06:35 +0300 Subject: [PATCH 0031/1064] Added/Updated tests\bugs\gh_4723_incompressible_test.py: Checked on 5.0.1.1399, 6.0.0.351 --- tests/bugs/gh_4723_incompressible_test.py | 137 ++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/bugs/gh_4723_incompressible_test.py diff --git a/tests/bugs/gh_4723_incompressible_test.py b/tests/bugs/gh_4723_incompressible_test.py new file mode 100644 index 00000000..1d1af1ed --- /dev/null +++ b/tests/bugs/gh_4723_incompressible_test.py @@ -0,0 +1,137 @@ +#coding:utf-8 + +""" +ID: issue-4723 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/4723 +TITLE: Optimize the record-level RLE algorithm for a denser compression of shorter-than-declared strings and sets of subsequent NULLs [CORE4401] +DESCRIPTION: + Test creates table with nullable varchar column an adds lot of rows with incompressible data (GEN_UUID). + Then we run gstat in order to parse statistics related to avg record length ('-r' switch). + + gstat reports for data pages and avg ratio following values: + 4.0.5.3099: + Average record length: 33018.92, total records: 10000 + Average unpacked length: 32766.00, compression ratio: 0.99 + Pointer pages: 1, data page slots: 632 + Data pages: 632, average fill: 92% + 5.0.1.1399, 6.0.0.351: + Average record length: 32757.00, total records: 10000 + Average unpacked length: 32766.00, compression ratio: 1.00 + Pointer pages: 1, data page slots: 304 + Data pages: 304, average fill: 87% + + Test assumes that values returned for 5.x will not be change in too wide range for several upcoming years + in any order - see MIN_* and MAX_* thresholds. +NOTES: + [20.05.2024] pzotov + Improvement URL (27-sep-2022 15:16): + https://github.com/FirebirdSQL/firebird/commit/54f1990b98d3e510a10d06fe9ceb76456804da52 + Improved record compression (denser encoding of repeating bytes and less blocks) (#7302) + + Charset must be specified in db_factory, otherwise 'malformed string' will raise. + Checked on 5.0.1.1399, 6.0.0.351 for DB with page_size = 8192. +""" +import re + +import pytest +import platform +from firebird.qa import * + +N_ROWS = 10000 +N_WIDT = 32760 + +MIN_DP_COUNT_THRESHOLD = 280 +MAX_DP_COUNT_THRESHOLD = 330 + +COMPRESSION_THRESHOLD = 1.00 + +init_ddl = f""" + recreate table test (f01 varchar({N_WIDT}) character set octets not null); + commit; + + set term ^; + execute block as + declare n int = {N_ROWS}; + begin + while (n > 0) do + begin + insert into test(f01) values( lpad('', 32760, gen_uuid()) ); + n = n - 1; + end + end + ^ + set term ;^ + commit; +""" + +db = db_factory(page_size = 8192, init = init_ddl, charset = 'win1251') +act = python_act('db') + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + act.gstat(switches=['-r', '-t', 'TEST', '-user', act.db.user, '-pass', act.db.password]) + gstat_lines = act.stdout.splitlines() + + #for p in gstat_lines: + # print(p) + # + #act.expected_stdout = f""" + #""" + #act.stdout = capsys.readouterr().out + #assert act.clean_stdout == act.clean_expected_stdout + + + # Average record length: N.FF, total records: M + # NB: for improved RLE value must be LESS OR EQUAL to the table column declared length + p_average_record_length = re.compile( r'Average\s+record\s+length(:)?\s+\d+(.\d+)?' ) + + # Average unpacked length: N.FF, compression ratio: R.PP + # NB: for improved RLE value must be 1.00 because column contrains incompressible data + p_compression_ratio = re.compile( r'Average\s+unpacked\s+length(:)?\s+\d+(.\d+)?(,)?\s+compression\s+ratio:\s+\d+(.\d+)?' ) + + # Pointer pages: N, data page slots: M + p_pointer_pages_data_pages_slots = re.compile( r'Pointer\s+pages(:)?\s+\d+(,)?\s+data\s+page\s+slots(:)?\s+\d+' ) + + average_record_length = compression_ratio = data_pages_cnt = -1 + gstat_lines = act.stdout.splitlines() + for line in gstat_lines: + if p_average_record_length.search(line): + # 'Average record length: 32757.00, total records: 10000' --> 32757 + average_record_length = int(float(line.replace(',','').split()[3])) + if p_compression_ratio.search(line): + # 'Average unpacked length: 32766.00, compression ratio: 1.00' + compression_ratio = float(line.split()[-1]) + if p_pointer_pages_data_pages_slots.search(line): + data_pages_cnt = int(line.split()[-1]) + + + assert average_record_length > 0 and compression_ratio > 0 and data_pages_cnt > 0 + + avg_rec_len_expected_msg = f'average_record_length -- expected: LESS OR EQUALS to declared column length = {N_WIDT}' + if average_record_length <= N_WIDT: + print(avg_rec_len_expected_msg) + else: + print(f'average_record_length -- UNEXPECTED: {average_record_length} - more than declared withd = {N_WIDT}') + + #------------------------------------------------------------------------------------------- + compression_ratio_expected_msg = f'compression_ratio_expected_msg -- expected: >= {COMPRESSION_THRESHOLD}' + if compression_ratio >= COMPRESSION_THRESHOLD: + print(compression_ratio_expected_msg) + else: + print(f'compression_ratio -- UNEXPECTED: {compression_ratio} - less than {COMPRESSION_THRESHOLD} (wasted compression occurred)') + + #------------------------------------------------------------------------------------------- + data_pages_cnt_expected_msg = f'data_pages_cnt: expected, within {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}' + if data_pages_cnt >= MIN_DP_COUNT_THRESHOLD and data_pages_cnt <= MAX_DP_COUNT_THRESHOLD: + print(data_pages_cnt_expected_msg) + else: + print(f'data_pages_cnt UNEXPECTED: {data_pages_cnt=} -- out of scope: {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}') + + act.expected_stdout = f""" + {avg_rec_len_expected_msg} + {compression_ratio_expected_msg} + {data_pages_cnt_expected_msg} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 69bc95847aee340178ac866b19159de7d68054e1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 20 May 2024 13:07:39 +0300 Subject: [PATCH 0032/1064] Renamed file --- tests/bugs/gh_4723_all_nulls_test.py | 112 +++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/bugs/gh_4723_all_nulls_test.py diff --git a/tests/bugs/gh_4723_all_nulls_test.py b/tests/bugs/gh_4723_all_nulls_test.py new file mode 100644 index 00000000..1d7ddda2 --- /dev/null +++ b/tests/bugs/gh_4723_all_nulls_test.py @@ -0,0 +1,112 @@ +#coding:utf-8 + +""" +ID: issue-4723 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/4723 +TITLE: Optimize the record-level RLE algorithm for a denser compression of shorter-than-declared strings and sets of subsequent NULLs [CORE4401] +DESCRIPTION: + Test creates table with nullable varchar column an adds lot of rows with NULL value. + Then we run gstat in order to parse statistics related to data pages and avg fill ratio. + gstat reports for data pages and avg ratio following values: + 4.0.5.3099: + Pointer pages: 2, data page slots: 2144 + Data pages: 2144, average fill: 91% + 5.0.1.1399, 6.0.0.351: + Pointer pages: 1, data page slots: 208 + Data pages: 208, average fill: 46% + Test assumes that values returned for 5.x will not be change in too wide range for several upcoming years + in any order - see MIN_* and MAX_* thresholds. +NOTES: + [20.05.2024] pzotov + Improvement URL (27-sep-2022 15:16): + https://github.com/FirebirdSQL/firebird/commit/54f1990b98d3e510a10d06fe9ceb76456804da52 + Improved record compression (denser encoding of repeating bytes and less blocks) (#7302) + + NB: snapshots that were just before and after this commit CAN NOT be verified: + 5.0.0.745: raised BUGCHECK ("decompression overran buffer (179), file: sqz.cpp line: 293") + 5.0.0.756: crashed + Checked on 5.0.1.1399, 6.0.0.351 for DB with page_size = 8192. +""" +import re + +import pytest +import platform +from firebird.qa import * + +N_ROWS = 30000 +N_WIDT = 32760 + +MIN_DP_COUNT_THRESHOLD = 190 +MAX_DP_COUNT_THRESHOLD = 230 +MIN_AVG_FILL_THRESHOLD = 30 +MAX_AVG_FILL_THRESHOLD = 60 + +init_ddl = f""" + recreate table test (f01 varchar({N_WIDT})); + commit; + + set term ^; + execute block as + declare n int = {N_ROWS}; + begin + while (n > 0) do + begin + insert into test(f01) values(null); + n = n - 1; + end + end + ^ + set term ;^ + commit; +""" + +db = db_factory(page_size = 8192, init = init_ddl) +act = python_act('db') + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + act.gstat(switches=['-d','-t', 'TEST', '-user', act.db.user, '-pass', act.db.password]) + + # 4.x: Pointer pages: 2, data page slots: 2144 + # 5.x: Pointer pages: 1, data page slots: 208 + p_pointer_pages_data_pages_slots = re.compile( r'Pointer\s+pages(:)?\s+\d+(,)?\s+data\s+page\s+slots(:)?\s+\d+' ) + + # Data pages: 208, average fill: 46% + p_data_pages_average_fill_ratio = re.compile( r'Data\s+pages(:)?\s+\d+(,)?\s+average\s+fill(:)?\s+\d+%' ) + + data_pages_cnt = avg_fill_ratio = -1 + gstat_lines = act.stdout.splitlines() + for line in gstat_lines: + #print(line) + if p_pointer_pages_data_pages_slots.search(line): + data_pages_cnt = int(line.split()[-1]) + if p_data_pages_average_fill_ratio.search(line): + avg_fill_ratio = int(line.split()[-1].replace('%','')) + + + data_pages_cnt_expected_msg = f'data_pages_cnt: expected, within {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}' + avg_fill_ratio_expected_msg = f'avg_fill_ratio: expected, within {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}' + if data_pages_cnt > 0 and avg_fill_ratio > 0: + if data_pages_cnt >= MIN_DP_COUNT_THRESHOLD and data_pages_cnt <= MAX_DP_COUNT_THRESHOLD: + print(data_pages_cnt_expected_msg) + else: + print(f'data_pages_cnt UNEXPECTED: {data_pages_cnt=} -- out of scope: {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}') + + if avg_fill_ratio >= MIN_AVG_FILL_THRESHOLD and avg_fill_ratio <= MAX_AVG_FILL_THRESHOLD: + print(avg_fill_ratio_expected_msg) + else: + print(f'avg_fill_ratio UNEXPECTED: {avg_fill_ratio=} -- out of scope: {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}') + else: + print(f'ERROR: at least one of: {data_pages_cnt=}, {avg_fill_ratio=} is INVALID.') + print('Could not properly parse gstat output:') + for p in gstat_lines: + print(p) + + act.expected_stdout = f""" + {data_pages_cnt_expected_msg} + {avg_fill_ratio_expected_msg} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From e451a68baa1a70f1c596121366631581caa14555 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 21 May 2024 09:10:54 +0300 Subject: [PATCH 0033/1064] Added/Updated tests\bugs\gh_8123_test.py: Checked on intermediate snapshots 6.0.0.357-f94343e, 5.0.1.1404-88bf561. --- tests/bugs/gh_8123_test.py | 163 +++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 tests/bugs/gh_8123_test.py diff --git a/tests/bugs/gh_8123_test.py b/tests/bugs/gh_8123_test.py new file mode 100644 index 00000000..ac25d1e8 --- /dev/null +++ b/tests/bugs/gh_8123_test.py @@ -0,0 +1,163 @@ +#coding:utf-8 + +""" +ID: issue-8123 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8123 +TITLE: Procedure manipulation can lead to wrong dependencies removal +DESCRIPTION: + Test verifies ticket notes for standalone procedure, standalone function and package which contains SP. + Before fix problem did exist in procedure (standalone and packaged): DROP command led to missed record + in rdb$dependencies and if we further try to drop TABLE then error with wrong SQLSTATE raised: + "SQLSTATE = 42S22 / invalid request BLR at offset 5 / -column N1 is not defined in table ..." + Expected error: + "SQLSTATE = 42000 / ... / -cannot delete ... / -there are 1 dependencies" +NOTES: + [21.05.2024] pzotov + Confirmed bug on 6.0.0.357-bf6c467 (regular daily snapshot, 18-may-2024). + Checked on intermediate snapshots 6.0.0.357-f94343e, 5.0.1.1404-88bf561. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + -- DO NOT set bail on! + set list on; + set count on; + + create table tb_test1 (n0 int, n1 integer, n2 integer computed by (n1)); + commit; + + create procedure sp_test (i1 type of column tb_test1.n2) as begin end; + commit; + + drop procedure sp_test; + commit; + + select + rdb$depended_on_name + ,rdb$field_name + ,rdb$dependent_type + ,rdb$depended_on_type + from rdb$dependencies + where rdb$depended_on_name = upper('tb_test1') and rdb$field_name = upper('n1'); + commit; + + alter table tb_test1 drop n1; + commit; + + -------------------------------------------------------------------------------- + + create table tb_test2 (n0 int, n1 integer, n2 integer computed by (n1)); + commit; + set term ^; + create function fn_test (i1 type of column tb_test2.n2) returns int as + begin + return 1; + end + ^ + set term ;^ + commit; + + drop function fn_test; + commit; + + select + rdb$depended_on_name + ,rdb$field_name + ,rdb$dependent_type + ,rdb$depended_on_type + from rdb$dependencies + where rdb$depended_on_name = upper('tb_test2') and rdb$field_name = upper('n1'); + commit; + + alter table tb_test2 drop n1; + commit; + + ----------------------------------------------------------------------------------- + + create table tb_test3 (n0 int, n1 integer, n2 integer computed by (n1)); + commit; + + set term ^; + create or alter package pg_test as + begin + procedure sp_worker (i1 type of column tb_test3.n2); + end + ^ + recreate package body pg_test as + begin + procedure sp_worker (i1 type of column tb_test3.n2) as + begin + + end + end + ^ + set term ;^ + commit; + + drop package pg_test; + commit; + + select + rdb$depended_on_name + ,rdb$field_name + ,rdb$dependent_type + ,rdb$depended_on_type + from rdb$dependencies + where rdb$depended_on_name = upper('tb_test3') and rdb$field_name = upper('n1'); + commit; + + alter table tb_test3 drop n1; + commit; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + RDB$DEPENDED_ON_NAME TB_TEST1 + RDB$FIELD_NAME N1 + RDB$DEPENDENT_TYPE 3 + RDB$DEPENDED_ON_TYPE 0 + Records affected: 1 + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TB_TEST1.N1 + -there are 1 dependencies + + + RDB$DEPENDED_ON_NAME TB_TEST2 + RDB$FIELD_NAME N1 + RDB$DEPENDENT_TYPE 3 + RDB$DEPENDED_ON_TYPE 0 + Records affected: 1 + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TB_TEST2.N1 + -there are 1 dependencies + + + RDB$DEPENDED_ON_NAME TB_TEST3 + RDB$FIELD_NAME N1 + RDB$DEPENDENT_TYPE 3 + RDB$DEPENDED_ON_TYPE 0 + Records affected: 1 + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TB_TEST3.N1 + -there are 1 dependencies +""" + +@pytest.mark.version('>=5.0.1') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 364f6a9d713ce0a7f3a4ebcc016a305cf6c33723 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 22 May 2024 04:02:08 +0300 Subject: [PATCH 0034/1064] Added/Updated tests\bugs\gh_5867_test.py: Checked on 6.0.0.357, 5.0.1.1404, 4.0.5.3099 --- tests/bugs/gh_5867_test.py | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/bugs/gh_5867_test.py diff --git a/tests/bugs/gh_5867_test.py b/tests/bugs/gh_5867_test.py new file mode 100644 index 00000000..63bf28cd --- /dev/null +++ b/tests/bugs/gh_5867_test.py @@ -0,0 +1,73 @@ +#coding:utf-8 + +""" +ID: issue-5867 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5867 +TITLE: Add details on compression and crypt status of connection (fb_info_conn_flags) to getInfo() API call [CORE5601] +DESCRIPTION: + Custom driver config object ('db_cfg_object') is used: WireCompression and WireCrypt are client-side parameters. + Test checks all combinations of these parameters and compares them with values returned by query to mon$attachments. + Also, we have to compare these values with vuts in DbInfoCode.CONN_FLAGS -- all appropriate values must be equal. +NOTES: + [22.05.2024] pzotov + FB 3.x is not checked: there is no ability to get info about wire* parameters from mon$attachments table. + Checked on 6.0.0.357, 5.0.1.1404, 4.0.5.3099. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol, DatabaseError, DbInfoCode, ConnectionFlag + +db = db_factory() +act = python_act('db') + +@pytest.mark.version('>=4.0.0') +def test_1(act: Action, capsys): + + srv_cfg = driver_config.register_server(name = 'test_srv_gh_5867', config = '') + iter = 0 + for wcompr_iter in ('True','False'): + for wcrypt_iter in ('Disabled','Enabled'): + iter += 1 + db_cfg_name = f'tmp_5867_wcompr_{wcompr_iter}_wcrypt_{wcrypt_iter}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + + db_cfg_object.config.value = f""" + WireCompression = {wcompr_iter} + WireCrypt = {wcrypt_iter} + """ + + dbcfg_wcompr = True if wcompr_iter == 'True' else False + dbcfg_wcrypt = True if wcrypt_iter == 'Enabled' else False + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.execute('select mon$wire_compressed, mon$wire_encrypted from mon$attachments where mon$attachment_id = current_connection') + mon_wire_compressed, mon_wire_encrypted = cur.fetchone()[:2] + con_flags_bits = con.info.get_info(DbInfoCode.CONN_FLAGS) + con_flags_wcompr = False if con_flags_bits & 0b01 == ConnectionFlag.NONE else True + con_flags_wcrypt = False if con_flags_bits & 0b10 == ConnectionFlag.NONE else True + + if dbcfg_wcompr == mon_wire_compressed and mon_wire_compressed == con_flags_wcompr \ + and dbcfg_wcrypt == mon_wire_encrypted and mon_wire_encrypted == con_flags_wcrypt: + print(f'Check # {iter}: expected.') + else: + print('Check # {iter} - MISMATCH:') + print(f"Set in db_cfg: WireCompression = {dbcfg_wcompr}, WireCrypt = {dbcfg_wcrypt}") + print(f'mon$attachments: {mon_wire_compressed=}, {mon_wire_encrypted=}') + print(f'DbInfoCode.CONN_FLAGS: {con_flags_wcompr=}, {con_flags_wcrypt=}') + except DatabaseError as exc: + print(exc.__str__()) + + act.expected_stdout = """ + Check # 1: expected. + Check # 2: expected. + Check # 3: expected. + Check # 4: expected. + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 9187237eb614049a818a6335807c8aefdb1cd300 Mon Sep 17 00:00:00 2001 From: Dimitry Sibiryakov Date: Fri, 24 May 2024 17:34:36 +0200 Subject: [PATCH 0035/1064] Make test pass on debug build --- tests/bugs/core_2780_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_2780_test.py b/tests/bugs/core_2780_test.py index 3cf60680..0db50555 100644 --- a/tests/bugs/core_2780_test.py +++ b/tests/bugs/core_2780_test.py @@ -30,7 +30,7 @@ -- Sufixes: 'Firebird' followed by space and at least one digit. ,iif( cast(mon$client_version as varchar(255) character set utf8) collate unicode_ci similar to - '(WI|LI|UI|UP|SI|SO|HU)[-](T|V){0,1}[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)[[:WHITESPACE:]]+firebird[[:WHITESPACE:]]+[0-9]+((.?[0-9]+)*)%', 1, 0) is_client_version_valid + '(WI|LI|UI|UP|SI|SO|HU)[-](T|V){0,1}[0-9]+.[0-9]+.[0-9]+((.?[0-9]+)*)([-]dev)?[[:WHITESPACE:]]+firebird[[:WHITESPACE:]]+[0-9]+((.?[0-9]+)*)%', 1, 0) is_client_version_valid from mon$attachments where mon$attachment_id = current_connection; """ From bac6153253c1cc628d90e4add7f72c882ce8fb5a Mon Sep 17 00:00:00 2001 From: Dimitry Sibiryakov Date: Fri, 24 May 2024 17:44:11 +0200 Subject: [PATCH 0036/1064] And another one --- tests/functional/basic/isql/test_01.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/basic/isql/test_01.py b/tests/functional/basic/isql/test_01.py index 5a99bd40..623184c6 100644 --- a/tests/functional/basic/isql/test_01.py +++ b/tests/functional/basic/isql/test_01.py @@ -18,6 +18,7 @@ ('Number of DB pages free.*', 'Number of DB pages free'), ('Sweep.*', 'Sweep'), ('Forced Writes.*', 'Forced Writes'), ('Transaction -.*', ''), ('ODS.*', 'ODS'), + ('DB =.*', ''), ('Host = .*', ''), ('Wire crypt plugin.*', 'Wire crypt plugin'), ('Creation date.*', 'Creation date'), ('Protocol version.*', 'Protocol version'), From 54e65ad79af56115a969913175d7dbce706ed724 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 27 May 2024 10:44:27 +0300 Subject: [PATCH 0037/1064] Added/Updated tests\bugs\gh_8077_test.py: Checked on 6.0.0.362, 5.0.1.1408, 4.0.5.3103 (all SS/CS). --- tests/bugs/gh_8077_test.py | 158 +++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 tests/bugs/gh_8077_test.py diff --git a/tests/bugs/gh_8077_test.py b/tests/bugs/gh_8077_test.py new file mode 100644 index 00000000..64255602 --- /dev/null +++ b/tests/bugs/gh_8077_test.py @@ -0,0 +1,158 @@ +#coding:utf-8 + +""" +ID: issue-8077 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8077 +TITLE: Error "Too many recursion levels" does not stop execuition of code that uses ON DISCONNECT trigger (FB 4.x+) +DESCRIPTION: + Test creates DB-triggers 'ON CONNECT' and 'ON DISCONNECT', plus table 'LOG' for logging actions performed by DB-triggers. + Trigger 'ON DISCONNECT' makes EDS with new role thus creating new connection which will then be immediately finished and, + in turn, fire again this trigger. Eventually this must cause ISQL to terminate and firebird.log must contain errors. + Difference between old and new firebird.log must contain exactly two errors about detahc problem + (Error at disconnect: / Execute statement error at attach : / 335544830 : Too many recursion levels of EXECUTE STATEMENT) +NOTES: + [27.05.2024] pzotov + Time of ISQL execution is limited by MAX_WAIT_FOR_ISQL_TERMINATE seconds. Currently it is ~6s for SS and ~18s for CS. + + Checked on 6.0.0.362, 5.0.1.1408, 4.0.5.3103 (all SS/CS). +""" + +import re +from difflib import unified_diff +import pytest +import time +from pathlib import Path +import subprocess +import locale + +import firebird.driver +from firebird.qa import * + +db = db_factory() +substitutions = [ + ('^((?!(E|e)rror|statement|recursion|source|rdb_trg|trigger|ext_pool_active|isql_outcome).)*$', '') + ,('Execute statement error.*', 'Execute statement error') + ,('Firebird::.*', 'Firebird::') + ,('line(:)?\\s+\\d+.*', '') + ,('[ \t]+', ' ') + ] +act = python_act('db', substitutions = substitutions) + +tmp_sql = temp_file('tmp_8077.sql') +tmp_log = temp_file('tmp_8077.log') + +MAX_WAIT_FOR_ISQL_BEGIN_WORK=0.5 +MAX_WAIT_FOR_ISQL_TERMINATE=30 + +#-------------------------------------------------------------------- + +@pytest.mark.version('>=4.0.5') +def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): + + test_sql = f""" + set list on; + set bail on; + + set term ^; + create or alter trigger trg_attach on connect as begin end + ^ + recreate table log( att bigint default current_connection, event_name varchar(6) ) + ^ + create or alter trigger trg_attach on connect as + declare v_pool_size int; + begin + in autonomous transaction do + insert into log(event_name) values ('attach'); + end + ^ + create or alter trigger trg_detach on disconnect as + begin + execute statement ('insert into log(event_name) values(?)') ('detach') + with autonomous transaction + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user '{act.db.user}' password '{act.db.password}' role 'R' || replace(uuid_to_char(gen_uuid()),'-','') + ; + end + ^ + set term ;^ + commit; + select + rdb$trigger_name as "rdb_trg_name" + ,rdb$trigger_type as "rdb_trg_type" + from rdb$triggers + where rdb$system_flag is distinct from 1 + order by rdb$trigger_name; + rollback; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + select cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_SIZE') as int) as "ext_pool_size_1" from rdb$database; + quit; + """ + with open(tmp_sql, 'w') as f: + f.write(test_sql) + + # Get Firebird log before test + # ---------------------------- + fb_log_init = act.get_firebird_log() + failed_finish_isql_msg = '' + with act.db.connect() as con: + with open(tmp_log, 'w') as f: + try: + p_handed_isql = subprocess.Popen( [act.vars['isql'], '-i', str(tmp_sql), + '-user', act.db.user, + '-password', act.db.password, act.db.dsn], + stdout = f, + stderr = subprocess.STDOUT + ) + + for i in range(MAX_WAIT_FOR_ISQL_TERMINATE): + time.sleep(1) + # Check if child process has terminated. + # Set and return returncode attribute. Otherwise, returns None. + if p_handed_isql.poll() is not None: + break + + finally: + p_handed_isql.terminate() + + if p_handed_isql.poll() is None: + failed_finish_isql_msg = f'isql_outcome: process WAS NOT terminated in {MAX_WAIT_FOR_ISQL_TERMINATE} second. Probably MAX_WAIT_FOR_ISQL_TERMINATE value must be increased.' + + # Get Firebird log after test + # ---------------------------- + fb_log_curr = act.get_firebird_log() + + with open(tmp_log, 'a') as f: + if failed_finish_isql_msg: + f.write(failed_finish_isql_msg+'\n') + for line in unified_diff(fb_log_init, fb_log_curr): + if line.startswith('+'): + f.write(line[1:] + '\n') + + + expected_stdout = f""" + rdb_trg_name TRG_ATTACH + rdb_trg_type 8192 + rdb_trg_name TRG_DETACH + rdb_trg_type 8193 + + Error at disconnect: + Execute statement error at attach : + 335544830 : Too many recursion levels of EXECUTE STATEMENT + Data source : Firebird:: + At trigger 'TRG_DETACH' + + Error at disconnect: + Execute statement error at attach : + 335544830 : Too many recursion levels of EXECUTE STATEMENT + Data source : Firebird:: + At trigger 'TRG_DETACH' + """ + + with open(tmp_log, 'r') as f: + for line in f: + print(line) + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From e583eebdfd71441b26888c8eb82be4c827b7e81c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 27 May 2024 12:46:31 +0300 Subject: [PATCH 0038/1064] Added/Updated tests\bugs\gh_8120_test.py: Checked on 6.0.0.362; 5.0.1.1408; 4.0.5.3103 --- tests/bugs/gh_8120_test.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/bugs/gh_8120_test.py diff --git a/tests/bugs/gh_8120_test.py b/tests/bugs/gh_8120_test.py new file mode 100644 index 00000000..823f8113 --- /dev/null +++ b/tests/bugs/gh_8120_test.py @@ -0,0 +1,34 @@ +#coding:utf-8 + +""" +ID: issue-8120 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8120 +TITLE: Cast dies with numeric value is out of range error +DESCRIPTION: +NOTES: + [27.05.2024] pzotov + Confirmed bug on 4.0.5.3077. + Checked on 6.0.0.362; 5.0.1.1408; 4.0.5.3103 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set heading off; + select cast('27' as numeric(4,2)) from rdb$database; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + 27.00 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4d4a54dec7f096397b5c90fcf711faaf6eea4cd5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 28 May 2024 06:57:58 +0300 Subject: [PATCH 0039/1064] Added/Updated tests\bugs\gh_7676_test.py: Checked on 5.0.0.1121 --- tests/bugs/gh_7676_test.py | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/bugs/gh_7676_test.py diff --git a/tests/bugs/gh_7676_test.py b/tests/bugs/gh_7676_test.py new file mode 100644 index 00000000..47752c7d --- /dev/null +++ b/tests/bugs/gh_7676_test.py @@ -0,0 +1,39 @@ +#coding:utf-8 + +""" +ID: issue-7676 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7676 +TITLE: Attempt to evaluate index expression recursively +DESCRIPTION: +NOTES: + [28.05.2024] pzotov + Confirmed bug on 5.0.0.1111: got SQLSTATE = HY000 / Attempt to evaluate index expression recursively + Checked on 5.0.0.1121. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + create table test(x int); + create unique index test_unq on test computed by (x); + commit; + insert into test values(1); + insert into test values(1); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "TEST_UNQ" + -Problematic key value is ( = 1) +""" + +@pytest.mark.version('>=5.0.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From bdc84dcd8b00ed79f60d1830ee2053b6f81c887d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 28 May 2024 06:59:31 +0300 Subject: [PATCH 0040/1064] Added/Updated tests\bugs\gh_7676_test.py: adjusted title --- tests/bugs/gh_7676_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_7676_test.py b/tests/bugs/gh_7676_test.py index 47752c7d..b2c777f9 100644 --- a/tests/bugs/gh_7676_test.py +++ b/tests/bugs/gh_7676_test.py @@ -3,7 +3,7 @@ """ ID: issue-7676 ISSUE: https://github.com/FirebirdSQL/firebird/issues/7676 -TITLE: Attempt to evaluate index expression recursively +TITLE: Invalid message when violating unique constraint ("Attempt to evaluate index expression recursively") DESCRIPTION: NOTES: [28.05.2024] pzotov From 2682c12f745b9c38e76ab07be959b4c920d3671b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 28 May 2024 11:43:03 +0300 Subject: [PATCH 0041/1064] Added/Updated tests\bugs\gh_8136_test.py: Checked on 6.0.0.363-40d0b41, 5.0.1.1408-c432bd0 --- tests/bugs/gh_8136_test.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/bugs/gh_8136_test.py diff --git a/tests/bugs/gh_8136_test.py b/tests/bugs/gh_8136_test.py new file mode 100644 index 00000000..a1ef76eb --- /dev/null +++ b/tests/bugs/gh_8136_test.py @@ -0,0 +1,34 @@ +#coding:utf-8 + +""" +ID: issue-8136 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8136 +TITLE: Server crashes with IN (dbkey1, dbkey2, ...) condition +DESCRIPTION: +NOTES: + [28.05.2024] pzotov + Confirmed crash on 6.0.0.36, 5.0.1.1408 + Checked on 6.0.0.363-40d0b41, 5.0.1.1408-c432bd0 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set heading off; + select 1 from rdb$database where rdb$db_key in (MAKE_DBKEY(1, 0), MAKE_DBKEY(1, 1)); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + 1 +""" + +@pytest.mark.version('>=5.0.1') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 58e3be0b860f1a2c3849846e803be355aa424c28 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 29 May 2024 21:38:53 +0300 Subject: [PATCH 0042/1064] Added/Updated tests\functional\tabloid\test_95442bdf.py: Checked on intermediate snapshot 6.0.0.363 #95442bd. --- tests/functional/tabloid/test_95442bdf.py | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/functional/tabloid/test_95442bdf.py diff --git a/tests/functional/tabloid/test_95442bdf.py b/tests/functional/tabloid/test_95442bdf.py new file mode 100644 index 00000000..11f9a6bd --- /dev/null +++ b/tests/functional/tabloid/test_95442bdf.py @@ -0,0 +1,83 @@ +#coding:utf-8 + +""" +ID: issue-95442bdf +ISSUE: https://github.com/FirebirdSQL/firebird/commit/95442bdfff76d22aafb57b58894047be2a89c6ea +TITLE: Attempt to avoid hash joining for possible cardinality under-estimations +DESCRIPTION: + Test verifies explained plan for three forms of inner join: + * 'normal' (or 'traditional'): 'from A join B on ' + * 'using': 'from A join B using () + * 'natural': 'from A natural join B' + All forms must generate same plan with nested loops (i.e. without hash join). + Lines in each explained plan are LETF-PADDED with dot character in order to keep indentation while + analyzing differences between expected and actual output. +NOTES: + [29.05.2024] pzotov + Checked on intermediate snapshot 6.0.0.363 #95442bd. + Thanks to dimitr for provided example. +""" + +import pytest +from firebird.qa import * + +init_sql = f""" + create table t1(id int); + create table t2(id int primary key using index t2_pk); + insert into t1(id) select row_number()over() from rdb$types,rdb$types; + 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('>=6.0') +def test_1(act: Action, capsys): + + join_expr_lst = ( + 't1 a join t2 b on a.id = b.id' + ,'t1 u join t2 v using(id)' + ,'t1 x natural join t2 y' + ) + + with act.db.connect() as con: + cur = con.cursor() + for x in join_expr_lst: + with cur.prepare(f'select * from ' + x) as ps: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan .split('\n')]) ) + + act.expected_stdout = """ + Select Expression + ....-> Nested Loop Join (inner) + ........-> Table "T1" as "A" Full Scan + ........-> Filter + ............-> Table "T2" as "B" Access By ID + ................-> Bitmap + ....................-> Index "T2_PK" Unique Scan + + Select Expression + ....-> Nested Loop Join (inner) + ........-> Table "T1" as "U" Full Scan + ........-> Filter + ............-> Table "T2" as "V" Access By ID + ................-> Bitmap + ....................-> Index "T2_PK" Unique Scan + + Select Expression + ....-> Nested Loop Join (inner) + ........-> Table "T1" as "X" Full Scan + ........-> Filter + ............-> Table "T2" as "Y" Access By ID + ................-> Bitmap + ....................-> Index "T2_PK" Unique Scan + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 14035a7304fb769c01f506014e2a26e2a08edb18 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 30 May 2024 14:19:40 +0300 Subject: [PATCH 0043/1064] Added/Updated tests\bugs\gh_7141_test.py: Checked on 6.0.0.363, 5.0.1.1408, 4.0.5.3103, 3.0.12.33744 --- tests/bugs/gh_7141_test.py | 139 +++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tests/bugs/gh_7141_test.py diff --git a/tests/bugs/gh_7141_test.py b/tests/bugs/gh_7141_test.py new file mode 100644 index 00000000..1f649216 --- /dev/null +++ b/tests/bugs/gh_7141_test.py @@ -0,0 +1,139 @@ +#coding:utf-8 + +""" +ID: issue-7141 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7141 +TITLE: Services manager breaks long lines into 1023 bytes portions when using isc_info_svc_line in Service::query() +DESCRIPTION: + Test invokes fbsvcmgr utility with requirement to start sepaarate trace session which will have long name. + This name is stored in variable LONG_NAME_OF_TRACE_SESSION and its maximal len currently is 16254. + Then we try to find this name in two ways: + * using act.connect_server().trace.sessions.items(); + * using fbsvcmgr action_trace_list. + Both way must return info which contains without line breaking (this is what was fixed). +NOTES: + Confirmed bug on 4.0.1.2735, 3.0.10.33570: name of session did contain LF characters in its middle points. + Confirmed problem on 5.0.0.418 - but only for console FB utility (fbsvcmgr), and NOT for usage firebird-QA framework + (it causes BUGCHECK "decompression overran buffer (179), file: sqz.cpp line: 293" on test teardown phase). + Checked on 6.0.0.363, 5.0.1.1408, 4.0.5.3103, 3.0.12.33744 +""" + +import pytest +import platform +import re +from firebird.qa import * +from pathlib import Path +import subprocess +import time + +#db = db_factory(async_write = False) +db = db_factory() +act = python_act('db') + +tmp_trace_cfg = temp_file('test_trace_7141.cfg') +tmp_trace_log = temp_file('test_trace_7141.log') + +MAX_WAIT_FOR_TRACE_STOP = 10 +TRC_SESSION_NAME_PREFIX = 'gh_7141_' +TRC_SESSION_NAME_MAX_LEN = 16254 + +# 65000 100000 --> FileNotFoundError: [WinError 206] The filename or extension is too long // in localized form! +# 32000 --> AssertionError: Could not find trace session to be stopped in {act.connect_server().trace.sessions.items()=} // None +LONG_NAME_OF_TRACE_SESSION = (TRC_SESSION_NAME_PREFIX * 10000000)[:TRC_SESSION_NAME_MAX_LEN] +EXPECTED_MSG1 = 'Success: found trace session name in act.connect_server().trace.sessions.items()' +EXPECTED_MSG2 = 'Success: found trace session name in the result of fbsvcmgr action_trace_list' + +@pytest.mark.trace +@pytest.mark.version('>=3.0.10') +def test_1(act: Action, tmp_trace_cfg: Path, tmp_trace_log: Path, capsys): + + trace_txt = f""" + database=%[\\\\/]{act.db.db_path.name} + {{ + enabled = true + log_initfini = false + }} + """ + + tmp_trace_cfg.write_text(trace_txt) + trace_session_id = -1 + trace_session_nm = '' + + with tmp_trace_log.open('w') as f_log: + # EXPLICIT call of FB utility 'fbsvcmgr': + p = subprocess.Popen( [ act.vars['fbsvcmgr'], + 'localhost:service_mgr', + 'user', act.db.user, + 'password', act.db.password, + 'action_trace_start', + 'trc_name', LONG_NAME_OF_TRACE_SESSION, + 'trc_cfg', tmp_trace_cfg + ], + stdout = f_log, stderr = subprocess.STDOUT + ) + time.sleep(1.1) + + q1 = subprocess.run( [ act.vars['fbsvcmgr'], + 'localhost:service_mgr', + 'user', act.db.user, + 'password', act.db.password, + 'action_trace_list', + ], + stdout = f_log, stderr = subprocess.STDOUT + ) + + assert q1.returncode == 0 + + with act.connect_server() as srv: + # K = 1 + # V = TraceSession(id=1, user='SYSDBA', timestamp=..., name=, flags=['active', ' trace']) + for k,v in srv.trace.sessions.items(): + if v.flags[0] == 'active' and v.name.startswith(TRC_SESSION_NAME_PREFIX): + trace_session_id = v.id + trace_session_nm = v.name + + assert trace_session_id > 0, f'Could not find trace session to be stopped in {act.connect_server().trace.sessions.items()=}' + + q2 = subprocess.run( [ act.vars['fbsvcmgr'], + 'localhost:service_mgr', + 'user', act.db.user, + 'password', act.db.password, + 'action_trace_stop', + 'trc_id', str(trace_session_id) + ], + stdout = f_log, stderr = subprocess.STDOUT, + timeout = MAX_WAIT_FOR_TRACE_STOP + ) + + time.sleep(1.1) + if not p.poll(): + p.terminate() + assert q2.returncode == 0 + + if trace_session_nm == LONG_NAME_OF_TRACE_SESSION: + print(EXPECTED_MSG1) + else: + print('UNEXPECTED. COULD NOT FIND trace session name in in act.connect_server().trace.sessions.items()') + + p_prefix_in_list = re.compile(f'name(:)?\\s+{TRC_SESSION_NAME_PREFIX}', re.IGNORECASE) + + found_in_trc_list = False + with tmp_trace_log.open('r') as f_log: + for line in f_log: + #if p_prefix_in_list.search(line): + if LONG_NAME_OF_TRACE_SESSION in line: + found_in_trc_list = True + print(EXPECTED_MSG2) + break + + if not found_in_trc_list: + print('Check result of fbsvcmgr action_trace_list:') + with tmp_trace_log.open('r') as f: + print(f.read()) + + act.expected_stdout = f""" + {EXPECTED_MSG1} + {EXPECTED_MSG2} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From f7afa0199e5f0d27f44d02960f7cfca0e5b4788f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 3 Jun 2024 09:50:00 +0300 Subject: [PATCH 0044/1064] Added/Updated tests\bugs\gh_5995_test.py: Checked on 6.0.0.366, 5.0.1.1411, 4.0.5.3103 --- tests/bugs/gh_5995_test.py | 316 +++++++++++++++++++++---------------- 1 file changed, 183 insertions(+), 133 deletions(-) diff --git a/tests/bugs/gh_5995_test.py b/tests/bugs/gh_5995_test.py index 5a198638..5df7b063 100644 --- a/tests/bugs/gh_5995_test.py +++ b/tests/bugs/gh_5995_test.py @@ -5,150 +5,200 @@ ISSUE: 5995 TITLE: Connection to server may hang when working with encrypted databases over non-TCP protocol DESCRIPTION: - Test implemented only to be run on Windows. - It assumes that there are files keyholder.dll and keyholder.conf in the %FIREBIRD_HOME%\\plugins dir. - These files were provided by IBSurgeon and added during fbt_run prepare phase by batch scenario (qa_rundaily). - File keyholder.conf initially contains several keys. + Test implemented only to be run on Windows. + Folder %FIREBIRD_HOME%/plugins/ must have files fbSampleKeyHolder.conf and fbSampleKeyHolder.dll which should be + copied there from %FIREBIRD_HOME%/examples/prebuilt/plugins/. + NB! These files ABSENT in FB 3.x but they can be taken from FB 4.x snapshot. + File fbSampleKeyHolder.conf must have following lines: + Auto = true + KeyRed=111 - If we make this file EMPTY then usage of XNET and WNET protocols became improssible before this ticket was fixed. - Great thanks to Alex for suggestions. - - Confirmed bug on 3.0.1.32609: ISQL hangs on attempt to connect to database when file plugins\\keyholder.conf is empty. - In order to properly finish test, we have to kill hanging ISQL and change DB state to full shutdown (with subsequent - returning it to online) - fortunately, connection using TCP remains avaliable in this case. + If we encrypt database and then make file fbSampleKeyHolder.conf EMPTY then usage of XNET and WNET protocols became + impossible before this ticket was fixed. + Great thanks to Alex for suggestions. JIRA: CORE-5730 FBTEST: bugs.gh_5995 +NOTES: + [03.06.2024] pzotov + Confirmed bug on 3.0.1.32609, 4.0.0.853: ISQL hangs on attempt to connect to database when file plugins/keyholder.conf is empty. + Checked on 6.0.0.366, 5.0.1.1411, 4.0.5.3103 (all of them were checked for ServerMode = SS and CS). + + ATTENTION: 3.x raises different SQLSTATE and error text, depending on ServerMode! + For 3.x value of SQLSTATE and error text depends on Servermode. + On Classic FB 3.x output will be almost like in FB 4.x+: + Statement failed, SQLSTATE = 08004 + Missing correct crypt key + -Plugin fbSampleDbCrypt: + -Crypt key Red not set + -IProvider::attachDatabase failed when loading mapping cache + On Super FB 3.x output is: + Statement failed, SQLSTATE = HY000 + Missing correct crypt key + -Plugin fbSampleDbCrypt: + -Crypt key Red not set + Because of that, it was decided not to check FB 3.x as this version soon will be considered as obsolete. """ +import shutil +import locale +import re +import time +import platform +import subprocess + +import datetime as py_dt +from pathlib import Path + import pytest from firebird.qa import * +from firebird.driver import DatabaseError, DbInfoCode, NetProtocol + +import time + +########################### +### S E T T I N G S ### +########################### + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +enc_settings = QA_GLOBALS['encryption'] + +# ACHTUNG: this must be carefully tuned on every new host: +# +MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN']) +assert MAX_WAITING_ENCR_FINISH > 0 + +ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt +ENCRYPTION_KEY = enc_settings['encryption_key'] # Red db = db_factory() +act = python_act('db', substitutions = [('After line \\d+.*', ''),('[ \t]+', ' ')]) -act = python_act('db') +kholder_cfg_bak = temp_file('fbSampleKeyHolder.bak') +tmp_sql = temp_file('tmp_5995.sql') +tmp_log = temp_file('tmp_5995.log') -expected_stdout = """ - MON$REMOTE_PROTOCOL WNET - MON$REMOTE_PROTOCOL XNET -""" +#----------------------------------------------------------------------- + +def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): + + assert mode in ('encrypt', 'decrypt') -@pytest.mark.skip('FIXME: Not IMPLEMENTED') -@pytest.mark.version('>=3.0.4') + if mode == 'encrypt': + alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}" key "{ENCRYPTION_KEY}"' + wait_for_state = 'Database encrypted' + elif mode == 'decrypt': + alter_db_sttm = 'alter database decrypt' + wait_for_state = 'Database not encrypted' + + e_thread_finished = False + + d1 = py_dt.timedelta(0) + with act.db.connect() as con: + #cur = con.cursor() + #ps = cur.prepare('select mon$crypt_state from mon$database') + + t1=py_dt.datetime.now() + try: + d1 = t1-t1 + con.execute_immediate(alter_db_sttm) + con.commit() + # Pattern to check for completed encryption thread: + completed_encr_pattern = re.compile(f'Attributes\\s+encrypted,\\s+plugin\\s+{ENCRYPTION_PLUGIN}', re.IGNORECASE) + while not e_thread_finished: + t2=py_dt.datetime.now() + d1=t2-t1 + if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: + break + + ############################################# + ### C H E C K G S T A T A T T R. ### + ############################################# + # Invoke 'gstat -h' and read its ouput. + # Encryption can be considered as COMPLETED when we will found: + # "Attributes encrypted, plugin fbSampleDbCrypt" + # + act.gstat(switches=['-h']) + for line in act.stdout.splitlines(): + if mode == 'encrypt' and completed_encr_pattern.match(line.strip()): + e_thread_finished = True + if mode == 'decrypt' and 'Attributes' in line and not completed_encr_pattern.search(line.strip()): + e_thread_finished = True + if e_thread_finished: + break + + time.sleep(0.5) + + except DatabaseError as e: + print( e.__str__() ) + + assert e_thread_finished, f'TIMEOUT EXPIRATION: {mode=} took {d1.seconds*1000 + d1.microseconds//1000} ms which greater than {max_wait_encr_thread_finish=} ms' + +#----------------------------------------------------------------------- + +@pytest.mark.encryption +@pytest.mark.version('>=4.0') @pytest.mark.platform('Windows') -def test_1(act: Action): - pytest.fail("Not IMPLEMENTED") +def test_1(act: Action, kholder_cfg_bak: Path, tmp_sql: Path, tmp_log: Path, capsys): + kholder_cfg_file = act.vars['home-dir'] / 'plugins' / 'fbSampleKeyHolder.conf' + shutil.copy2(kholder_cfg_file, kholder_cfg_bak) + finish_encryption = False -# test_script_1 -#--- -# -# import os -# import subprocess -# from subprocess import Popen -# import datetime -# import time -# import shutil -# import re -# import fdb -# -# os.environ["ISC_USER"] = user_name -# os.environ["ISC_PASSWORD"] = user_password -# engine = db_conn.engine_version -# db_name = db_conn.database_name -# db_conn.close() -# -# svc = fdb.services.connect(host='localhost', user=user_name, password=user_password) -# FB_HOME = svc.get_home_directory() -# svc.close() -# -# #-------------------------------------------- -# -# def flush_and_close( file_handle ): -# # https://docs.python.org/2/library/os.html#os.fsync -# # If you're starting with a Python file object f, -# # first do f.flush(), and -# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk. -# global os -# -# file_handle.flush() -# if file_handle.mode not in ('r', 'rb') and file_handle.name != os.devnull: -# # otherwise: "OSError: [Errno 9] Bad file descriptor"! -# os.fsync(file_handle.fileno()) -# file_handle.close() -# -# #-------------------------------------------- -# -# def cleanup( f_names_list ): -# global os -# for i in range(len( f_names_list )): -# if type(f_names_list[i]) == file: -# del_name = f_names_list[i].name -# elif type(f_names_list[i]) == str: -# del_name = f_names_list[i] -# else: -# print('Unrecognized type of element:', f_names_list[i], ' - can not be treated as file.') -# print('type(f_names_list[i])=',type(f_names_list[i])) -# del_name = None -# -# if del_name and os.path.isfile( del_name ): -# os.remove( del_name ) -# -# #-------------------------------------------- -# -# -# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") -# -# kholder_cur = os.path.join( FB_HOME, 'plugins', 'keyholder.conf') -# kholder_bak = os.path.join( context['temp_directory'], 'keyholder'+dts+'.bak') -# -# shutil.copy2( kholder_cur, kholder_bak) -# -# # Make file %FB_HOME%\\plugins\\keyholder.conf empty: -# with open(kholder_cur,'w') as f: -# pass -# -# MAX_SECONDS_TO_WAIT = 3 -# -# # Trying to establish connection to database using WNET and XNET protocols. -# # Async. launch of ISQL with check that it will finished within some reasonable time (and w/o errors). -# # If it will hang - kill (this is bug dexcribed in the ticket) -# for p in ('wnet', 'xnet'): -# f_isql_sql=open(os.path.join(context['temp_directory'],'tmp_gh_5995.'+p+'.sql'),'w') -# f_isql_sql.write('set list on; select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection;') -# flush_and_close( f_isql_sql ) -# -# protocol_conn_string = ''.join( (p, '://', db_name) ) -# f_isql_log=open( os.path.join(context['temp_directory'],'tmp_gh_5995.'+p+'.log'), 'w') -# p_isql = Popen([ context['isql_path'], protocol_conn_string, "-i", f_isql_sql.name], stdout=f_isql_log, stderr=subprocess.STDOUT ) -# -# time.sleep(0.2) -# for i in range(0,MAX_SECONDS_TO_WAIT): -# # Check if child process has terminated. Set and return returncode attribute. Otherwise, returns None. -# p_isql.poll() -# if p_isql.returncode is None: -# # A None value indicates that the process has not terminated yet. -# time.sleep(1) -# if i < MAX_SECONDS_TO_WAIT-1: -# continue -# else: -# f_isql_log.write( '\\nISQL process %d hangs for %d seconds and is forcedly killed.' % (p_isql.pid, MAX_SECONDS_TO_WAIT) ) -# p_isql.terminate() -# -# flush_and_close(f_isql_log) -# -# with open(f_isql_log.name,'r') as f: -# for line in f: -# if line: -# print(line) -# -# cleanup((f_isql_sql,f_isql_log)) -# -# shutil.move( kholder_bak, kholder_cur) -# -# # ::: NOTE ::: We have to change DB state to full shutdown and bring it back online -# # in order to prevent "Object in use" while fbtest will try to drop this DB -# ##################################### -# runProgram('gfix',[dsn,'-shut','full','-force','0']) -# runProgram('gfix',[dsn,'-online']) -# -# -#--- + protocols_list = [ NetProtocol.INET, NetProtocol.XNET, ] + if act.is_version('<5'): + protocols_list.append(NetProtocol.WNET) + + expected_output = actual_output = test_sql = '' + try: + run_encr_decr(act, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys) + finish_encryption = True + with open(kholder_cfg_file,'w') as f: + pass + + for protocol_name in protocols_list: + conn_str = f"connect {protocol_name.name.lower()}://{act.db.db_path} user {act.db.user} password '{act.db.password}'" + test_sql = f""" + set list on; + set bail on; + set echo on; + {conn_str}; + select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection; + """ + tmp_sql.write_text(test_sql) + + with open(tmp_log, 'w') as f_log: + # ISQL-4.x must issue: + # Statement failed, SQLSTATE = 08004 + # Missing database encryption key for your attachment + # -Plugin fbSampleDbCrypt: + # -Crypt key Red not set + # Before fix, ISQL hanged on CONNECT, thus we have to use timeout here! + # + p = subprocess.run( [ act.vars['isql'], + '-q', + '-i', str(tmp_sql) + ], + stdout = f_log, stderr = subprocess.STDOUT, + timeout = 3 + ) + + actual_output += tmp_log.read_text() + + expected_output += f""" + {conn_str}; + Statement failed, SQLSTATE = 08004 + Missing database encryption key for your attachment + -Plugin {ENCRYPTION_PLUGIN}: + -Crypt key {ENCRYPTION_KEY} not set + """ + + except Exception as e: + actual_output += test_sql + '\n' + e.__str__() + finally: + shutil.copy2(kholder_cfg_bak, kholder_cfg_file) + if finish_encryption: + run_encr_decr(act, 'decrypt', MAX_WAITING_ENCR_FINISH, capsys) + + act.expected_stdout = expected_output + act.stdout = actual_output # capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From a68cac9c9dd867487245246e02ac02ebceb85d7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 5 Jun 2024 11:20:37 +0300 Subject: [PATCH 0045/1064] Added/Updated tests\functional\transactions\test_read_consist_sttm_merge_deny_multiple_matches.py: added forgotten 'order by' clause. Deadlock otherwise can occur. Thanks to Vlad for note. --- .../test_read_consist_sttm_merge_deny_multiple_matches.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py b/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py index 2aa275ea..d97100a4 100644 --- a/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py +++ b/tests/functional/transactions/test_read_consist_sttm_merge_deny_multiple_matches.py @@ -185,6 +185,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: using ( select s.id, s.x from {target_obj} as s where s.id <= 1 + order by s.id DESC -- added only 05-jun-2024; thanks to Vlad. ) s on abs(t.id) = abs(s.id) when matched then From 35c594a5f9f78c158f825e7cad1d48f9ec2c0156 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 9 Jun 2024 14:36:52 +0300 Subject: [PATCH 0046/1064] Added/Updated tests\bugs\gh_8077_test.py: Added threshold in order to prevent infinite recursion in case of regression. See notes in the code, variable 'STOP_RECURSIVE_ES_AFTER_ITER'. --- tests/bugs/gh_8077_test.py | 63 +++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/tests/bugs/gh_8077_test.py b/tests/bugs/gh_8077_test.py index 64255602..e9ee4e6d 100644 --- a/tests/bugs/gh_8077_test.py +++ b/tests/bugs/gh_8077_test.py @@ -14,6 +14,12 @@ [27.05.2024] pzotov Time of ISQL execution is limited by MAX_WAIT_FOR_ISQL_TERMINATE seconds. Currently it is ~6s for SS and ~18s for CS. + [08.06.2024] pzotov + Added threshold in order to prevent infinite recursion in case of regression. + Otherwise this test can cause collapse of test machine because of infinite launch of firebird processes (in case of Classic). + See notes in the code below, variable 'STOP_RECURSIVE_ES_AFTER_ITER'. + Checked on snapshot 5.x that was not yet fixed. + Checked on 6.0.0.362, 5.0.1.1408, 4.0.5.3103 (all SS/CS). """ @@ -28,9 +34,10 @@ import firebird.driver from firebird.qa import * -db = db_factory() +db = db_factory(do_not_drop = True) +#db = db_factory() substitutions = [ - ('^((?!(E|e)rror|statement|recursion|source|rdb_trg|trigger|ext_pool_active|isql_outcome).)*$', '') + ('^((?!(E|e)rror|exception|statement|recursion|source|rdb_trg|trigger|ext_pool_active|isql_outcome).)*$', '') ,('Execute statement error.*', 'Execute statement error') ,('Firebird::.*', 'Firebird::') ,('line(:)?\\s+\\d+.*', '') @@ -44,6 +51,23 @@ MAX_WAIT_FOR_ISQL_BEGIN_WORK=0.5 MAX_WAIT_FOR_ISQL_TERMINATE=30 +# ### NOTE ### +# We have to define generator and increment it on each DB-level trigger invocation in order to prevent infinite loop +# if its value will be greater than some threshold (in case if regression will occur and engine for some reason will +# not able to detect too deep recursion). +# Value of this generator will be compared with threshold ('STOP_RECURSIVE_ES_AFTER_ITER') and no further recursive +# calls will be executed if generator exceeds this threshold. +# But value of threshold STOP_RECURSIVE_ES_AFTER_ITER must NOT be too small. +# Otherwise following message will be MESSED from output: +# Error at disconnect: +# Execute statement error +# 335544830 : Too many recursion levels of EXECUTE STATEMENT +# Data source : Firebird:: +# At trigger 'TRG_DETACH' +# Currently last value of this sequence (after exception raising) is 99 for both SS and CS. +# +STOP_RECURSIVE_ES_AFTER_ITER = 101 + #-------------------------------------------------------------------- @pytest.mark.version('>=4.0.5') @@ -54,24 +78,42 @@ def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): set bail on; set term ^; + create or alter trigger trg_detach on disconnect as begin end + ^ create or alter trigger trg_attach on connect as begin end ^ - recreate table log( att bigint default current_connection, event_name varchar(6) ) + create sequence g_attach + ^ + create sequence g_detach + ^ + create sequence g_diff + ^ + create exception exc_too_deep_recursion 'Execution terminated by @1: recursion depth exceeded the threshold @2 by @3' + ^ + recreate table log(id int primary key, att bigint default current_connection, event_name varchar(6) ) ^ create or alter trigger trg_attach on connect as declare v_pool_size int; begin - in autonomous transaction do - insert into log(event_name) values ('attach'); + if ( gen_id(g_attach,0) <= {STOP_RECURSIVE_ES_AFTER_ITER} ) then + in autonomous transaction do + insert into log(id, event_name) values (-gen_id(g_attach,1), 'attach'); + else + exception exc_too_deep_recursion using ('trg_attach', {STOP_RECURSIVE_ES_AFTER_ITER}, gen_id(g_attach,1) - {STOP_RECURSIVE_ES_AFTER_ITER} - 1) + ; end ^ create or alter trigger trg_detach on disconnect as begin - execute statement ('insert into log(event_name) values(?)') ('detach') - with autonomous transaction - on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user '{act.db.user}' password '{act.db.password}' role 'R' || replace(uuid_to_char(gen_uuid()),'-','') - ; + if ( gen_id(g_detach,0) <= {STOP_RECURSIVE_ES_AFTER_ITER} ) then + execute statement ('insert into log(id, event_name) values(?, ?)') (gen_id(g_detach,1), 'detach') + with autonomous transaction + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user '{act.db.user}' password '{act.db.password}' role 'R' || replace(uuid_to_char(gen_uuid()),'-','') + ; + else + exception exc_too_deep_recursion using ('trg_detach', {STOP_RECURSIVE_ES_AFTER_ITER}, gen_id(g_detach,1) - {STOP_RECURSIVE_ES_AFTER_ITER} - 1) + ; end ^ set term ;^ @@ -84,7 +126,6 @@ def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): order by rdb$trigger_name; rollback; connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - select cast(rdb$get_context('SYSTEM', 'EXT_CONN_POOL_SIZE') as int) as "ext_pool_size_1" from rdb$database; quit; """ with open(tmp_sql, 'w') as f: From fe0e96d7a145abff590f681d71ef1a5aa04e4d54 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 9 Jun 2024 15:36:09 +0300 Subject: [PATCH 0047/1064] Reduced StatementTimeout to reasonable value. It is pre-database configurable thus one can easy to adjust it to any particular test requirements where this value must be set to greater number. --- configs/fb40_all.conf | 2 +- configs/fb50_all.conf | 2 +- configs/fb60_all.conf | 2 +- tests/bugs/gh_4723_test.py | 112 ------------------------------------- 4 files changed, 3 insertions(+), 115 deletions(-) delete mode 100644 tests/bugs/gh_4723_test.py diff --git a/configs/fb40_all.conf b/configs/fb40_all.conf index a6acff9f..103e7311 100644 --- a/configs/fb40_all.conf +++ b/configs/fb40_all.conf @@ -68,7 +68,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 7200 +StatementTimeout = 300 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 diff --git a/configs/fb50_all.conf b/configs/fb50_all.conf index f9cf2095..a811cdcd 100644 --- a/configs/fb50_all.conf +++ b/configs/fb50_all.conf @@ -70,7 +70,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 7200 +StatementTimeout = 300 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 diff --git a/configs/fb60_all.conf b/configs/fb60_all.conf index 21796ec5..ebb4196a 100644 --- a/configs/fb60_all.conf +++ b/configs/fb60_all.conf @@ -70,7 +70,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 7200 +StatementTimeout = 300 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 diff --git a/tests/bugs/gh_4723_test.py b/tests/bugs/gh_4723_test.py deleted file mode 100644 index 1d7ddda2..00000000 --- a/tests/bugs/gh_4723_test.py +++ /dev/null @@ -1,112 +0,0 @@ -#coding:utf-8 - -""" -ID: issue-4723 -ISSUE: https://github.com/FirebirdSQL/firebird/issues/4723 -TITLE: Optimize the record-level RLE algorithm for a denser compression of shorter-than-declared strings and sets of subsequent NULLs [CORE4401] -DESCRIPTION: - Test creates table with nullable varchar column an adds lot of rows with NULL value. - Then we run gstat in order to parse statistics related to data pages and avg fill ratio. - gstat reports for data pages and avg ratio following values: - 4.0.5.3099: - Pointer pages: 2, data page slots: 2144 - Data pages: 2144, average fill: 91% - 5.0.1.1399, 6.0.0.351: - Pointer pages: 1, data page slots: 208 - Data pages: 208, average fill: 46% - Test assumes that values returned for 5.x will not be change in too wide range for several upcoming years - in any order - see MIN_* and MAX_* thresholds. -NOTES: - [20.05.2024] pzotov - Improvement URL (27-sep-2022 15:16): - https://github.com/FirebirdSQL/firebird/commit/54f1990b98d3e510a10d06fe9ceb76456804da52 - Improved record compression (denser encoding of repeating bytes and less blocks) (#7302) - - NB: snapshots that were just before and after this commit CAN NOT be verified: - 5.0.0.745: raised BUGCHECK ("decompression overran buffer (179), file: sqz.cpp line: 293") - 5.0.0.756: crashed - Checked on 5.0.1.1399, 6.0.0.351 for DB with page_size = 8192. -""" -import re - -import pytest -import platform -from firebird.qa import * - -N_ROWS = 30000 -N_WIDT = 32760 - -MIN_DP_COUNT_THRESHOLD = 190 -MAX_DP_COUNT_THRESHOLD = 230 -MIN_AVG_FILL_THRESHOLD = 30 -MAX_AVG_FILL_THRESHOLD = 60 - -init_ddl = f""" - recreate table test (f01 varchar({N_WIDT})); - commit; - - set term ^; - execute block as - declare n int = {N_ROWS}; - begin - while (n > 0) do - begin - insert into test(f01) values(null); - n = n - 1; - end - end - ^ - set term ;^ - commit; -""" - -db = db_factory(page_size = 8192, init = init_ddl) -act = python_act('db') - -@pytest.mark.version('>=5.0') -def test_1(act: Action, capsys): - - act.gstat(switches=['-d','-t', 'TEST', '-user', act.db.user, '-pass', act.db.password]) - - # 4.x: Pointer pages: 2, data page slots: 2144 - # 5.x: Pointer pages: 1, data page slots: 208 - p_pointer_pages_data_pages_slots = re.compile( r'Pointer\s+pages(:)?\s+\d+(,)?\s+data\s+page\s+slots(:)?\s+\d+' ) - - # Data pages: 208, average fill: 46% - p_data_pages_average_fill_ratio = re.compile( r'Data\s+pages(:)?\s+\d+(,)?\s+average\s+fill(:)?\s+\d+%' ) - - data_pages_cnt = avg_fill_ratio = -1 - gstat_lines = act.stdout.splitlines() - for line in gstat_lines: - #print(line) - if p_pointer_pages_data_pages_slots.search(line): - data_pages_cnt = int(line.split()[-1]) - if p_data_pages_average_fill_ratio.search(line): - avg_fill_ratio = int(line.split()[-1].replace('%','')) - - - data_pages_cnt_expected_msg = f'data_pages_cnt: expected, within {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}' - avg_fill_ratio_expected_msg = f'avg_fill_ratio: expected, within {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}' - if data_pages_cnt > 0 and avg_fill_ratio > 0: - if data_pages_cnt >= MIN_DP_COUNT_THRESHOLD and data_pages_cnt <= MAX_DP_COUNT_THRESHOLD: - print(data_pages_cnt_expected_msg) - else: - print(f'data_pages_cnt UNEXPECTED: {data_pages_cnt=} -- out of scope: {MIN_DP_COUNT_THRESHOLD=} ... {MAX_DP_COUNT_THRESHOLD=}') - - if avg_fill_ratio >= MIN_AVG_FILL_THRESHOLD and avg_fill_ratio <= MAX_AVG_FILL_THRESHOLD: - print(avg_fill_ratio_expected_msg) - else: - print(f'avg_fill_ratio UNEXPECTED: {avg_fill_ratio=} -- out of scope: {MIN_AVG_FILL_THRESHOLD=} ... {MAX_AVG_FILL_THRESHOLD=}') - else: - print(f'ERROR: at least one of: {data_pages_cnt=}, {avg_fill_ratio=} is INVALID.') - print('Could not properly parse gstat output:') - for p in gstat_lines: - print(p) - - act.expected_stdout = f""" - {data_pages_cnt_expected_msg} - {avg_fill_ratio_expected_msg} - """ - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - From 71b430dcd5345fbb668be1b9ecac9aa552caa474 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 9 Jun 2024 18:34:02 +0300 Subject: [PATCH 0048/1064] Added mark es_eds to mark tests as dealing with ES/EDS mechanism --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index 04a3cfd4..f94fcd5a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,6 +3,7 @@ console_output_style = count # testpaths = tests # addopts = --server local --install-terminal markers = + es_eds: mark a test as dealing with ES/EDS mechanism trace: mark a test as dealing with trace encryption: mark a test as dealing with encryption plugin replication: mark a test as dealing with database participating in replication From 188f82dba7e8c6a932ebbb3363ea5967410f5de8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 9 Jun 2024 18:53:05 +0300 Subject: [PATCH 0049/1064] Set '@pytest.mark.es_eds' to tests which relate to ES/EDS mechanism. --- tests/bugs/core_0606_test.py | 2 +- tests/bugs/core_1361_test.py | 1 + tests/bugs/core_1606_test.py | 1 + tests/bugs/core_1930_test.py | 1 + tests/bugs/core_2018_test.py | 1 + tests/bugs/core_2252_test.py | 1 + tests/bugs/core_2305_test.py | 1 + tests/bugs/core_2668_test.py | 1 + tests/bugs/core_2731_test.py | 1 + tests/bugs/core_2987_test.py | 1 + tests/bugs/core_3100_test.py | 1 + tests/bugs/core_3554_test.py | 1 + tests/bugs/core_3610_test.py | 1 + tests/bugs/core_3736_test.py | 1 + tests/bugs/core_4054_test.py | 1 + tests/bugs/core_4161_test.py | 1 + tests/bugs/core_4326_test.py | 1 + tests/bugs/core_4396_test.py | 1 + tests/bugs/core_4604_test.py | 1 + tests/bugs/core_4707_test.py | 1 + tests/bugs/core_4747_test.py | 1 + tests/bugs/core_5225_test.py | 1 + tests/bugs/core_5229_test.py | 1 + tests/bugs/core_5488_running_sttm_test.py | 1 + tests/bugs/core_5555_test.py | 1 + tests/bugs/core_5648_test.py | 1 + tests/bugs/core_5685_test.py | 1 + tests/bugs/core_5704_test.py | 1 + tests/bugs/core_5898_test.py | 1 + tests/bugs/core_5985_test.py | 1 + tests/bugs/core_5990_test.py | 1 + tests/bugs/core_6182_test.py | 2 +- tests/bugs/gh_6886_test.py | 1 + tests/bugs/gh_7350_test.py | 1 + .../gh_7917_test-obj-in-use-on-drop-db.py | 419 ++++++++++++++++++ tests/bugs/gh_7917_test.py | 1 + tests/bugs/gh_8077_test.py | 1 + .../session/test_ext_conn_pool_01.py | 9 +- .../syspriv/test_access_shutdown_database.py | 1 + .../syspriv/test_monitor_any_attachment.py | 1 + 40 files changed, 458 insertions(+), 10 deletions(-) create mode 100644 tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py diff --git a/tests/bugs/core_0606_test.py b/tests/bugs/core_0606_test.py index 52bfaa93..738366e7 100644 --- a/tests/bugs/core_0606_test.py +++ b/tests/bugs/core_0606_test.py @@ -100,7 +100,7 @@ -At block line: 3, col: 7 """ - +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action, cvc_user: User, for_role: Role, for_cvc_role: Role): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_1361_test.py b/tests/bugs/core_1361_test.py index ed8fe911..41ca10ae 100644 --- a/tests/bugs/core_1361_test.py +++ b/tests/bugs/core_1361_test.py @@ -146,6 +146,7 @@ USING_INDEX 1 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_1606_test.py b/tests/bugs/core_1606_test.py index aca29362..0c737e25 100644 --- a/tests/bugs/core_1606_test.py +++ b/tests/bugs/core_1606_test.py @@ -120,6 +120,7 @@ PID 1 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_1930_test.py b/tests/bugs/core_1930_test.py index 9194d6c3..49bb081c 100644 --- a/tests/bugs/core_1930_test.py +++ b/tests/bugs/core_1930_test.py @@ -209,6 +209,7 @@ def test_1(act_1: Action): -At block line """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_2(act_2: Action): act_2.expected_stderr = expected_stderr_2 diff --git a/tests/bugs/core_2018_test.py b/tests/bugs/core_2018_test.py index bd35e539..eeb1723e 100644 --- a/tests/bugs/core_2018_test.py +++ b/tests/bugs/core_2018_test.py @@ -119,6 +119,7 @@ ATTACHES_I_CAN_SEE 11 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_2252_test.py b/tests/bugs/core_2252_test.py index a045fff2..61cd6660 100644 --- a/tests/bugs/core_2252_test.py +++ b/tests/bugs/core_2252_test.py @@ -77,6 +77,7 @@ -At block line: 11, col: 9 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_2305_test.py b/tests/bugs/core_2305_test.py index 013b16d3..522fad94 100644 --- a/tests/bugs/core_2305_test.py +++ b/tests/bugs/core_2305_test.py @@ -110,6 +110,7 @@ DISTINCT_STATEMENT_ID_THEY_SAW 1 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_2668_test.py b/tests/bugs/core_2668_test.py index f922eaac..e98a8921 100644 --- a/tests/bugs/core_2668_test.py +++ b/tests/bugs/core_2668_test.py @@ -63,6 +63,7 @@ tmp_script = temp_file('work_script.sql') +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action, tmp_script: Path): tmp_script.write_text(test_script) diff --git a/tests/bugs/core_2731_test.py b/tests/bugs/core_2731_test.py index e0fd9efb..091e369c 100644 --- a/tests/bugs/core_2731_test.py +++ b/tests/bugs/core_2731_test.py @@ -85,6 +85,7 @@ -At block line: 5, col: 5 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stderr = expected_stderr diff --git a/tests/bugs/core_2987_test.py b/tests/bugs/core_2987_test.py index e0e26b99..d6cf5907 100644 --- a/tests/bugs/core_2987_test.py +++ b/tests/bugs/core_2987_test.py @@ -152,6 +152,7 @@ MEASURE_RESULT WINS >= 3.8x """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3100_test.py b/tests/bugs/core_3100_test.py index 98a62c6b..39986d29 100644 --- a/tests/bugs/core_3100_test.py +++ b/tests/bugs/core_3100_test.py @@ -252,6 +252,7 @@ record not found for user: TMP$C3100B """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3554_test.py b/tests/bugs/core_3554_test.py index 4a25115d..4c7ac629 100644 --- a/tests/bugs/core_3554_test.py +++ b/tests/bugs/core_3554_test.py @@ -99,6 +99,7 @@ -At block line: 4, col: 7 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3610_test.py b/tests/bugs/core_3610_test.py index dde3b409..c6fa76a1 100644 --- a/tests/bugs/core_3610_test.py +++ b/tests/bugs/core_3610_test.py @@ -80,6 +80,7 @@ -At block line: 3, col: 9 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3736_test.py b/tests/bugs/core_3736_test.py index a9918177..0ea3ed70 100644 --- a/tests/bugs/core_3736_test.py +++ b/tests/bugs/core_3736_test.py @@ -143,6 +143,7 @@ 335544878 : concurrent transaction number is 806 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action, user_1_ro: User, user_1_ud: User): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4054_test.py b/tests/bugs/core_4054_test.py index c50a7f0e..29beea45 100644 --- a/tests/bugs/core_4054_test.py +++ b/tests/bugs/core_4054_test.py @@ -117,6 +117,7 @@ WHAT_I_SEE 789654123 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4161_test.py b/tests/bugs/core_4161_test.py index fb3c8201..f5e4351a 100644 --- a/tests/bugs/core_4161_test.py +++ b/tests/bugs/core_4161_test.py @@ -142,6 +142,7 @@ MINE_F01 300 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4326_test.py b/tests/bugs/core_4326_test.py index c49125bc..e283ad7b 100644 --- a/tests/bugs/core_4326_test.py +++ b/tests/bugs/core_4326_test.py @@ -91,6 +91,7 @@ LNAME Zeppelin """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4396_test.py b/tests/bugs/core_4396_test.py index a930dc1d..37683f9c 100644 --- a/tests/bugs/core_4396_test.py +++ b/tests/bugs/core_4396_test.py @@ -73,6 +73,7 @@ CNT 0 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4604_test.py b/tests/bugs/core_4604_test.py index 12e6d48f..78ff008f 100644 --- a/tests/bugs/core_4604_test.py +++ b/tests/bugs/core_4604_test.py @@ -91,6 +91,7 @@ STR_SIZE 36 """ +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4707_test.py b/tests/bugs/core_4707_test.py index fbf3be60..20f3ea96 100644 --- a/tests/bugs/core_4707_test.py +++ b/tests/bugs/core_4707_test.py @@ -68,6 +68,7 @@ hang_script_file = temp_file('hang_script.sql') hang_output = temp_file('hang_script.out') +@pytest.mark.es_eds @pytest.mark.version('>=2.5.5') def test_1(act: Action, hang_script_file: Path, hang_output: Path, capsys, request): # Fializer for FB4 diff --git a/tests/bugs/core_4747_test.py b/tests/bugs/core_4747_test.py index 08ebe429..a7b781b1 100644 --- a/tests/bugs/core_4747_test.py +++ b/tests/bugs/core_4747_test.py @@ -35,6 +35,7 @@ act = python_act('db', substitutions = substitutions) +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): diff --git a/tests/bugs/core_5225_test.py b/tests/bugs/core_5225_test.py index 9644e111..80c7debb 100644 --- a/tests/bugs/core_5225_test.py +++ b/tests/bugs/core_5225_test.py @@ -73,6 +73,7 @@ WHOAMI_SRP TMP$C5225 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0.1') def test_1(act: Action, user_srp: User, user_leg: User): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5229_test.py b/tests/bugs/core_5229_test.py index 030a8522..802d341d 100644 --- a/tests/bugs/core_5229_test.py +++ b/tests/bugs/core_5229_test.py @@ -30,6 +30,7 @@ """ @pytest.mark.skip("FIXME: see notes") +@pytest.mark.es_eds @pytest.mark.version('>=3.0.1') def test_1(act: Action): sql_chk = f""" diff --git a/tests/bugs/core_5488_running_sttm_test.py b/tests/bugs/core_5488_running_sttm_test.py index 033bf751..eadc4003 100644 --- a/tests/bugs/core_5488_running_sttm_test.py +++ b/tests/bugs/core_5488_running_sttm_test.py @@ -185,6 +185,7 @@ -Attachment level timeout expired. """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5555_test.py b/tests/bugs/core_5555_test.py index 3c8824fa..c5f1b76c 100644 --- a/tests/bugs/core_5555_test.py +++ b/tests/bugs/core_5555_test.py @@ -87,6 +87,7 @@ GDS_ON_SELECT_WITH_LOCK 335544336 """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0.3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5648_test.py b/tests/bugs/core_5648_test.py index 8d546c97..205d257b 100644 --- a/tests/bugs/core_5648_test.py +++ b/tests/bugs/core_5648_test.py @@ -40,6 +40,7 @@ eds_script = temp_file('eds_script.sql') +@pytest.mark.es_eds @pytest.mark.version('>=3.0.3') def test_1(act: Action, eds_script: Path): eds_sql = f""" diff --git a/tests/bugs/core_5685_test.py b/tests/bugs/core_5685_test.py index 998dc02c..c53fd123 100644 --- a/tests/bugs/core_5685_test.py +++ b/tests/bugs/core_5685_test.py @@ -152,6 +152,7 @@ hang_stderr = temp_file('hang_script.err') @pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') +@pytest.mark.es_eds @pytest.mark.version('>=3.0.3') def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path, capsys): diff --git a/tests/bugs/core_5704_test.py b/tests/bugs/core_5704_test.py index 38c27f95..4b8bccfe 100644 --- a/tests/bugs/core_5704_test.py +++ b/tests/bugs/core_5704_test.py @@ -44,6 +44,7 @@ new_diff_file = temp_file('_new_diff_5704.tmp') new_main_file = temp_file('new_main_5704.tmp') +@pytest.mark.es_eds @pytest.mark.version('>=3.0.3') def test_1(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path, new_main_file: Path): diff --git a/tests/bugs/core_5898_test.py b/tests/bugs/core_5898_test.py index 8cb7770a..5879b2df 100644 --- a/tests/bugs/core_5898_test.py +++ b/tests/bugs/core_5898_test.py @@ -99,6 +99,7 @@ WHAT_PROTOCOL_IM_USING """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0.4') def test_1(act: Action, tmp_user, tmp_role): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5985_test.py b/tests/bugs/core_5985_test.py index 122bfe47..e9056066 100644 --- a/tests/bugs/core_5985_test.py +++ b/tests/bugs/core_5985_test.py @@ -85,6 +85,7 @@ WHATS_MY_ROLE WORKER """ +@pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action, user_foo, user_bar): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5990_test.py b/tests/bugs/core_5990_test.py index e70a35bc..0d88ff3a 100644 --- a/tests/bugs/core_5990_test.py +++ b/tests/bugs/core_5990_test.py @@ -165,6 +165,7 @@ DUP_CNT 5 """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action): if int(act.get_config('ExtConnPoolSize')) < 6 or int(act.get_config('ExtConnPoolLifeTime')) < 10: diff --git a/tests/bugs/core_6182_test.py b/tests/bugs/core_6182_test.py index 6169931c..0e85e364 100644 --- a/tests/bugs/core_6182_test.py +++ b/tests/bugs/core_6182_test.py @@ -105,7 +105,7 @@ def init_main_db(act: Action, eds_user: User): """ act.isql(switches=[], input=ddl_script) - +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action, db_a: Database, db_b: Database, db_c: Database, db_d: Database, eds_user: User, capsys): diff --git a/tests/bugs/gh_6886_test.py b/tests/bugs/gh_6886_test.py index 3ddc5f8c..292251bc 100644 --- a/tests/bugs/gh_6886_test.py +++ b/tests/bugs/gh_6886_test.py @@ -78,6 +78,7 @@ Records affected: 0 """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0.1') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/gh_7350_test.py b/tests/bugs/gh_7350_test.py index e474e673..e4b6158b 100644 --- a/tests/bugs/gh_7350_test.py +++ b/tests/bugs/gh_7350_test.py @@ -448,6 +448,7 @@ ID=10 """ +@pytest.mark.es_eds @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): diff --git a/tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py b/tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py new file mode 100644 index 00000000..ee66ad67 --- /dev/null +++ b/tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py @@ -0,0 +1,419 @@ +#coding:utf-8 + +""" +ID: issue-7917 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7917 +TITLE: Hang in a case of error when sweep thread is attaching to database +DESCRIPTION: + Test uses preliminary created alias with KeyHolderPlugin that points to special configuration with name 'KH2'. + This configuration makes crypt plugin accept key ONLY from client app (in contrary to some other encryption-related tests). + DB-level triggers (ON CONNECT, ON DISCONNECT) are created for logging appropriate events (see table 'att_log'). + Then we run special SQL that uses autonomous transactions and ES/EDS. + This script will hang because of update-conflict after some number of transactions (see TX_NUMBER_BEFORE_HANG). + We run this script asynchronously, then reduce sweep interval to value SWP_INTERVAL_TO_CHECK that is less than TX_NUMBER_BEFORE_HANG, + change DB state to full shutdown and return it online. + At this point any connection to DB will fire AUTO SWEEP (normally this can be seen in firebird.log as 'Sweep is started by SWEEPER'). + We run ISQL that queries 'att_log' table and causes AUTO SWEEP. That ISQL has to normally detach from DB and we must see its results. +NOTES: + [28.12.2023] pzotov + 1. To make crypt plugin accept key only from client app, $FB_HOME/plugins.conf must contain following lines: + ================== + Plugin = KH2 { + Module = $(dir_plugins)/fbSampleKeyHolder + RegisterName = fbSampleKeyHolder + Config = KH2 + } + Config = KH2 { + Auto = false + } + ================== + QA-scenario (.bat and .sh) must add in advance content of $QA_ROOT/files/qa-plugins-supplement.conf to $FB_HOME/plugins.conf. + + 2. Demo-plugin (fbSampleKeyHolder) can transfer key over network only for default key which has no-name. + Because of this, command 'alter database encrypt with ' has no '... key ' tail. + See letter from Alex, 15.12.2023 16:16 + + 3. In case of regression caused by that bug, we have to be ready that FB will hang on this test! + + Great thanks to Alex for suggestions (discussion started 13.12.2023 13:18). + + Confirmed bug on 6.0.0.173. + Checked on 6.0.0.175, 5.0.0.1305, 4.0.5.3049 - but currenlyt only SuperServer works fine. + Classic has the same problem. Sent report to Alex, 28.12.2023 13:10. + + On 3.0.12.33726 error raises: + unsuccessful metadata update / -ALTER DATABASE failed / -Missing correct crypt key / -Plugin fbSampleDbCrypt: / -Crypt key not set + This problem not [yet] investogated. +""" +import os +import time +import datetime as py_dt +import subprocess +import locale +import re +from pathlib import Path + +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError + +REQUIRED_ALIAS = 'tmp_gh_7917_alias' + +########################### +### S E T T I N G S ### +########################### + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +enc_settings = QA_GLOBALS['encryption'] + +# ACHTUNG: this must be carefully tuned on every new host: +# +MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN' if os.name == 'nt' else 'MAX_WAIT_FOR_ENCR_FINISH_NIX']) +assert MAX_WAITING_ENCR_FINISH > 0 + +ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt +ENCRYPTION_KEY = enc_settings['encryption_key'] # Red + +SWP_INTERVAL_TO_CHECK = 100 +TX_NUMBER_BEFORE_HANG = SWP_INTERVAL_TO_CHECK + 10 + +MAX_WAIT_FOR_ISQL_TERMINATE=11 + +db = db_factory(filename = '#' + REQUIRED_ALIAS, do_not_drop = True) + +act = python_act('db', substitutions = [('^((?!(ISQL|Attributes)).)*$', ''), ('[ \t]+', ' '), ('TCPv(4|6)$', 'TCP')]) +#act = python_act('db') + +tmp_sql_file = temp_file('tmp_7917.sql') +tmp_log_file = temp_file('tmp_7917.log') + +#----------------------------------------------------------------------- + +def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): + if mode == 'encrypt': + # See letter from Alex, 15.12.2023 16:16 demo-plugin can not transfer named key over network. + # Because of that, we have to use following command WITHOUT adding 'key "{ENCRYPTION_KEY}"': + # ::: NB ::: One need to be sure that $FB_HOME/plugins.conf contains following lines: + # Plugin = KH2 { + # Module = $(dir_plugins)/fbSampleKeyHolder + # RegisterName = fbSampleKeyHolder + # Config = KH2 + # } + # Config = KH2 { + # Auto = false + # } + # Otherwise error will raise: + # unsuccessful metadata update + # -ALTER DATABASE failed + # -Missing database encryption key for your attachment + # -Plugin fbSampleDbCrypt: + # -Crypt key not set + # + alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}"' + wait_for_state = 'Database encrypted' + elif mode == 'decrypt': + alter_db_sttm = 'alter database decrypt' + wait_for_state = 'Database not encrypted' + + + e_thread_started = False + e_thread_finished = False + with act.db.connect() as con: + + t1=py_dt.datetime.now() + d1 = t1-t1 + try: + con.execute_immediate(alter_db_sttm) + con.commit() + e_thread_started = True + except DatabaseError as e: + print( e.__str__() ) + + while e_thread_started: + t2=py_dt.datetime.now() + d1=t2-t1 + if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: + print(f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms.') + break + + # Possible output: + # Database [not] encrypted + # Database encrypted, crypt thread not complete + act.isql(switches=['-q'], input = 'show database;', combine_output = True) + if wait_for_state in act.stdout: + if 'not complete' in act.stdout: + pass + else: + e_thread_finished = True + break + act.reset() + + act.expected_stdout = '' + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + assert e_thread_finished + + +#----------------------------------------------------------------------- + +@pytest.mark.es_eds +@pytest.mark.encryption +@pytest.mark.version('>=4.0.5') +@pytest.mark.platform('Windows') +def test_1(act: Action, tmp_sql_file: Path, tmp_log_file: Path, capsys): + + ''' + with act.db.connect() as con: + if act.vars['server-arch'] == 'SuperServer': + pass + else: + pytest.skip("Currently fixed only for SuperServer. Temporary SKIPPED.") + ''' + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_7598_alias = $(dir_sampleDb)/qa/tmp_gh_7598.fdb + # - then we extract filename: 'tmp_gh_7598.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + #---------------------------------------------------------------- + + run_encr_decr(act, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys) + + test_script = f""" + set bail on; + create table att_log( + att_prot varchar(15) + ,who_ami varchar(31) default current_user + ,att_id bigint default current_connection + ,trn_id bigint default current_transaction + ,evt_time time default 'now' + ,evt_name varchar(20) + ,swp_interval int + ); + set term ^; + create procedure sp_fill_dblevel_log(a_evt_name type of column att_log.evt_name) as + declare v_swp_interval int; + declare v_protocol type of column att_log.att_prot; + begin + insert into att_log( + att_prot + ,evt_name + ) values ( + rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL') + ,:a_evt_name + ); + + end + ^ + create or alter trigger trg_detach on disconnect as + begin + execute procedure sp_fill_dblevel_log('detach'); + end + ^ + create or alter trigger trg_attach on connect as + begin + execute procedure sp_fill_dblevel_log('attach'); + end + ^ + set term ;^ + commit; + + recreate table test(s varchar(36) unique); + insert into test(s) values('LOCKED_FOR_PAUSE'); + commit; + + set transaction read committed WAIT; + + update test set s = s where s = 'LOCKED_FOR_PAUSE'; + + set term ^; + execute block as + declare n int = {TX_NUMBER_BEFORE_HANG}; + declare v_role varchar(31); + begin + while (n > 0) do + in autonomous transaction do + insert into test(s) values( rpad('', 36, uuid_to_char(gen_uuid()) ) ) + returning :n-1 into n; + + v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); + + begin + execute statement ('update /* ES/EDS */ test set s = s where s = ?') ('LOCKED_FOR_PAUSE') + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user 'SYSDBA' password 'masterkey' role v_role + with autonomous transaction; + when any do + begin + end + end + + end + ^ + set term ;^ + set heading off; + select '-- shutdown me now --' from rdb$database; + """ + + tmp_sql_file.write_text(test_script) + + #---------------------------------------------------------------- + + # Reduce sweep interval to small value (that must be less than SQL_HANG_AFTER_TX_CNT): + # + act.gfix(switches=['-h', f'{SWP_INTERVAL_TO_CHECK}', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding()) + + with open(tmp_log_file, 'w') as f: + # Launch ISQL which will hang because update conflict. + # This ISQl will be 'self-terminated' further because we will change DB state to full shutdown: + # + p_handed_isql = subprocess.Popen([act.vars['isql'], '-nod', '-i', str(tmp_sql_file), + '-user', act.db.user, + '-password', act.db.password, act.db.dsn], + stdout = f, + stderr = subprocess.STDOUT) + + # Let ISQL time to establish connection and fall in hanging state: + time.sleep(3) + + try: + act.gfix(switches=['-shut', 'full', '-force', '0', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding()) + finally: + p_handed_isql.terminate() + + p_handed_isql.wait(MAX_WAIT_FOR_ISQL_TERMINATE) + if p_handed_isql.poll() is None: + print(f'Hanged ISQL process WAS NOT terminated in {MAX_WAIT_FOR_ISQL_TERMINATE} second(s).!') + else: + print(f'Hanged ISQL process terminated with retcode = {p_handed_isql.poll()}') + + # Result: log of hanged ISQL must contain now: + # Statement failed, SQLSTATE = 08003 + # connection shutdown + # -Database is shutdown. + + act.gfix(switches=['-online', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == '' + act.reset() + + # Must show: Attributes encrypted, plugin {ENCRYPTION_PLUGIN} - without 'shutdown'! + act.gstat(switches=['-h']) + print(act.stdout) + + #act.stdout = capsys.readouterr().out + #assert act.clean_stdout == act.clean_expected_stdout + #act.reset() + + + #---------------------------------------------------------------- + + TEST_QUERY = 'select att_prot,who_ami,evt_name from att_log order by trn_id' + final_sql = f""" + set count on; + set list on; + set echo on; + {TEST_QUERY}; + commit; + connect '{act.db.dsn}'; + drop database; + quit; + """ + tmp_sql_file.write_text(final_sql) + + with open(tmp_log_file, 'w') as f: + # Explained by Alex, letter 13-dec-2023 13:18. + # Following ISQL will create attach that provokes AUTO SWEEP (because Next - OST now greater than SWP_INTERVAL_TO_CHECK). + # Problem raised when other attachments were prohibited to use encryption key (and this is default behaviour). + # Before fix, SWEEEP was not allowed to use key from this ISQL-attachment. + # Following message was added in firebird.log: "Automatic sweep error /Missing database encryption key for your attachment" + # But despite problem with establishing connection by SWEEP, its thread already created appropriate lock at that point. + # As result, engine remained in wrong state after this: existied attachments could not be closed. + # Also, FB process could not be normally stopped. + + MAX_WAIT_AUTO_SWEEP_FINISH = 3 + p_chk_sql = subprocess.Popen( [ act.vars['isql'], + '-nod', '-i', str(tmp_sql_file), + '-user', act.db.user, + '-password', act.db.password, + act.db.dsn + ], + stdout = f, + stderr = subprocess.STDOUT, + ) + + # If the process does not terminate after timeout seconds, raise a TimeoutExpired exception. + # It is safe to catch this exception and retry the wait. + try: + p_chk_sql.wait(timeout = MAX_WAIT_AUTO_SWEEP_FINISH) + except subprocess.TimeoutExpired as e: + print(f'Could not obtain result for {MAX_WAIT_AUTO_SWEEP_FINISH} seconds:') + print(e.__str__()) + + p_chk_sql.terminate() + p_chk_sql.wait(MAX_WAIT_FOR_ISQL_TERMINATE) + + # Check if child process has terminated. Set and return returncode attribute. Otherwise, returns None. + if p_chk_sql.poll() is None: + print(f'Final ISQL process WAS NOT terminated in {MAX_WAIT_FOR_ISQL_TERMINATE} second(s).!') + else: + print(f'Final ISQL process terminated') + #print(f'Final ISQL process terminated with retcode = {p_chk_sql.poll()}') + + + # do NOT put here this: + #run_encr_decr(act, 'decrypt', MAX_WAITING_ENCR_FINISH, capsys) + # - otherwise pytest will not return control + + with open(tmp_log_file, 'r') as f: + for line in f: + if line.strip(): + print('final ISQL log:',line) + + act.expected_stdout = f""" + Hanged ISQL process terminated with retcode = 1 + Attributes encrypted, plugin {ENCRYPTION_PLUGIN} + + Final ISQL process terminated + final ISQL log: {TEST_QUERY}; + final ISQL log: ATT_PROT TCP + final ISQL log: WHO_AMI {act.db.user.upper()} + final ISQL log: EVT_NAME attach + + final ISQL log: ATT_PROT TCP + final ISQL log: WHO_AMI {act.db.user.upper()} + final ISQL log: EVT_NAME detach + + final ISQL log: Records affected: 2 + + final ISQL log: commit; + final ISQL log: drop database; + final ISQL log: quit; + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # NB! We have to decrypt database now. Otherwise teardown will fail with: + # firebird.driver.types.DatabaseError: Missing database encryption key for your attachment + # -Plugin fbSampleDbCrypt: + # -Crypt key not set + #run_encr_decr(act, 'decrypt', MAX_WAITING_ENCR_FINISH, capsys) diff --git a/tests/bugs/gh_7917_test.py b/tests/bugs/gh_7917_test.py index cfa692b4..7413ab15 100644 --- a/tests/bugs/gh_7917_test.py +++ b/tests/bugs/gh_7917_test.py @@ -166,6 +166,7 @@ def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): #----------------------------------------------------------------------- +@pytest.mark.es_eds @pytest.mark.encryption @pytest.mark.version('>=4.0.5') def test_1(act: Action, tmp_sql_file: Path, tmp_log_file: Path, tmp_gstat_log: Path, capsys): diff --git a/tests/bugs/gh_8077_test.py b/tests/bugs/gh_8077_test.py index e9ee4e6d..3ae6a0f5 100644 --- a/tests/bugs/gh_8077_test.py +++ b/tests/bugs/gh_8077_test.py @@ -70,6 +70,7 @@ #-------------------------------------------------------------------- +@pytest.mark.es_eds @pytest.mark.version('>=4.0.5') def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): diff --git a/tests/functional/session/test_ext_conn_pool_01.py b/tests/functional/session/test_ext_conn_pool_01.py index e0f80695..8cadd802 100644 --- a/tests/functional/session/test_ext_conn_pool_01.py +++ b/tests/functional/session/test_ext_conn_pool_01.py @@ -73,6 +73,7 @@ # ITER_LOOP_CNT = 3 +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action, tmp_user_freq: User, tmp_user_rare: User, tmp_cleaner_role: Role, capsys): @@ -244,14 +245,6 @@ def test_1(act: Action, tmp_user_freq: User, tmp_user_rare: User, tmp_cleaner_ro commit; ''' - ''' - print(sql_init) - act.expected_stdout = '' - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - act.reset() - ''' - act.expected_stdout = '' act.isql(switches = ['-q'], input = sql_init, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout diff --git a/tests/functional/syspriv/test_access_shutdown_database.py b/tests/functional/syspriv/test_access_shutdown_database.py index c2eb1e31..554516b5 100644 --- a/tests/functional/syspriv/test_access_shutdown_database.py +++ b/tests/functional/syspriv/test_access_shutdown_database.py @@ -62,6 +62,7 @@ -At block line """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action, tmp_user: User, tmp_role:Role, capsys): diff --git a/tests/functional/syspriv/test_monitor_any_attachment.py b/tests/functional/syspriv/test_monitor_any_attachment.py index 0f26491c..87d41696 100644 --- a/tests/functional/syspriv/test_monitor_any_attachment.py +++ b/tests/functional/syspriv/test_monitor_any_attachment.py @@ -139,6 +139,7 @@ Records affected: 1 """ +@pytest.mark.es_eds @pytest.mark.version('>=4.0') def test_1(act: Action, test_user, test_role): act.expected_stdout = expected_stdout From a932c47c4fd48b9930ec9ac9dc6a9bf21da080f8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 9 Jun 2024 20:42:44 +0300 Subject: [PATCH 0050/1064] Added/Updated tests\bugs\gh_8136_test.py: Added temporary mark 'disabled_in_forks' to SKIP this test when QA verifies *fork* rather than standard FB. --- tests/bugs/gh_8136_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/bugs/gh_8136_test.py b/tests/bugs/gh_8136_test.py index a1ef76eb..d755cc03 100644 --- a/tests/bugs/gh_8136_test.py +++ b/tests/bugs/gh_8136_test.py @@ -9,6 +9,9 @@ [28.05.2024] pzotov Confirmed crash on 6.0.0.36, 5.0.1.1408 Checked on 6.0.0.363-40d0b41, 5.0.1.1408-c432bd0 + + [09.06.2024] pzotov + Added temporary mark 'disabled_in_forks' to SKIP this test when QA verifies *fork* rather than standard FB. """ import pytest @@ -27,6 +30,7 @@ 1 """ +@pytest.mark.disabled_in_forks @pytest.mark.version('>=5.0.1') def test_1(act: Action): act.expected_stdout = expected_stdout From 393143dfa3526cf46b931d3cdb873d4b3f120088 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 12 Jun 2024 22:18:57 +0300 Subject: [PATCH 0051/1064] Added/Updated tests\bugs\core_4754_test.py: minor adjustments --- tests/bugs/core_4754_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4754_test.py b/tests/bugs/core_4754_test.py index 001f4716..4b066059 100644 --- a/tests/bugs/core_4754_test.py +++ b/tests/bugs/core_4754_test.py @@ -2,9 +2,8 @@ """ ID: issue-5058 -ISSUE: 5058 -TITLE: Bugcheck 167 (invalid SEND request) while working with GTT from several - attachments (using EXECUTE STATEMENT ... ON EXTERNAL and different roles) +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5058 +TITLE: Bugcheck 167 (invalid SEND request) while working with GTT from several attachments (using EXECUTE STATEMENT ... ON EXTERNAL and different roles) DESCRIPTION: JIRA: CORE-4754 FBTEST: bugs.core_4754 From 07f6218ea02b675082d2b65df6b5cdea5610d478 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 13 Jun 2024 10:13:02 +0300 Subject: [PATCH 0052/1064] Added/Updated tests\bugs\core_5229_test.py: Added check for ability to use IPv6. See notes. --- tests/bugs/core_5229_test.py | 117 ++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/tests/bugs/core_5229_test.py b/tests/bugs/core_5229_test.py index 802d341d..f2b44bfa 100644 --- a/tests/bugs/core_5229_test.py +++ b/tests/bugs/core_5229_test.py @@ -2,18 +2,28 @@ """ ID: issue-5508 -ISSUE: 5508 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5508 TITLE: Allow to enforce IPv4 or IPv6 in URL-like connection strings DESCRIPTION: -NOTES: -[04.02.2022] pcisar - Test may fail with IPv6. - For example it fails on my Linux OpenSuSE Tumbleweed with regular setup (IPv6 should not be disabled). - Test should IMHO check IPv4/IPv6 availability on test host before runs inet6:// check. JIRA: CORE-5229 FBTEST: bugs.core_5229 -""" +NOTES: + [04.02.2022] pcisar + Test may fail with IPv6. + For example it fails on my Linux OpenSuSE Tumbleweed with regular setup (IPv6 should not be disabled). + Test should IMHO check IPv4/IPv6 availability on test host before runs inet6:// check. + [13.06.2024] pzotov + 1. Added check for ability to use IPv6. + 2. Attempt to specify explicitly IPv6 address "[::1]" in ES/EDS causes error: + ======== + Statement failed, SQLSTATE = 42000 + External Data Source provider 'inet6://[' not found + ======== + Sent report to Vlad et al, waiting for fix. + Currently no concrete address is specified in ES/EDS. + Checked on 3.0.12.33744, 4.0.5.3103, 5.0.1.1411, 6.0.0.368 +""" import pytest from firebird.qa import * @@ -21,25 +31,64 @@ act = python_act('db') -expected_stdout = """ - PROCOTOL_WHEN_CONNECT_FROM_OS TCPv4 - PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv4 - PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv4 - PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv6 - PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv6 -""" +#------------------------------------------ +# https://stackoverflow.com/questions/66246308/detect-if-ipv6-is-supported-os-agnostic-no-external-program/66249915#66249915 +# https://stackoverflow.com/a/66249915 + +def check_ipv6_avail(): + import socket + import errno + + # On Windows, the E* constants will use the WSAE* values + # So no need to hardcode an opaque integer in the sets. + _ADDR_NOT_AVAIL = {errno.EADDRNOTAVAIL, errno.EAFNOSUPPORT} + _ADDR_IN_USE = {errno.EADDRINUSE} + + res = -1 + if not socket.has_ipv6: + # If the socket library has no support for IPv6, then the + # question is moot as we can't use IPv6 anyways. + return res + + sock = None + try: + #with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as sock: + # sock.bind(("::1", 0)) + sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + sock.bind(("::1", 0)) + #sock.shutdown(socket.SHUT_RDWR) # [Errno 107] Transport endpoint is not connected + sock.close() + res = 0 + except socket.error as x: + # sysctl net.ipv6.conf.all.disable_ipv6=1 + # sysctl net.ipv6.conf.default.disable_ipv6=1 + # sock.bind(("::1", 0)) --> socket.error: [Errno 99] Cannot assign requested address + #print(x) + res = -2 + except OSError as e: + if e.errno in _ADDR_NOT_AVAIL: + res = -3 + elif e.errno in _ADDR_IN_USE: + # This point shouldn't ever be reached. But just in case... + res = -4 + else: + # Other errors should be inspected + res = -5 + + return res +#------------------------------------------ -@pytest.mark.skip("FIXME: see notes") @pytest.mark.es_eds @pytest.mark.version('>=3.0.1') def test_1(act: Action): + + if (res := check_ipv6_avail()) < 0: + pytest.skip(f"IPv6 not avail, retcode: {res}") + sql_chk = f""" set list on; - select mon$remote_protocol as procotol_when_connect_from_os - from mon$attachments where mon$attachment_id = current_connection; - commit; - connect 'inet4://{act.db.db_path}'; + connect 'inet4://127.0.0.1/{act.db.db_path}'; select mon$remote_protocol as procotol_when_connect_from_isql from mon$attachments where mon$attachment_id = current_connection; @@ -50,7 +99,7 @@ def test_1(act: Action): begin for execute statement (stt) - on external 'inet4://{act.db.db_path}' + on external 'inet4://127.0.0.1/{act.db.db_path}' as user '{act.db.user}' password '{act.db.password}' into protocol_when_connect_by_es_eds do @@ -61,6 +110,8 @@ def test_1(act: Action): commit; -- since 27.10.2019: + -- inet6://[::1]/employee + -- connect 'inet6://[::1]/{act.db.db_path}'; connect 'inet6://{act.db.db_path}'; select mon$remote_protocol as procotol_when_connect_from_isql @@ -72,6 +123,7 @@ def test_1(act: Action): begin for execute statement (stt) + --on external 'inet6://[::1]/{act.db.db_path}' -- currently fails with on external 'inet6://{act.db.db_path}' as user '{act.db.user}' password '{act.db.password}' into protocol_when_connect_by_es_eds @@ -81,23 +133,16 @@ def test_1(act: Action): ^ set term ;^ commit; + """ + + expected_stdout = """ + PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv4 + PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv4 + PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv6 + PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv6 + """ - -- |||||||||||||||||||||||||||| - -- ###################################||| FB 4.0+, SS and SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - delete from mon$attachments where mon$attachment_id != current_connection; - commit; - """ act.expected_stdout = expected_stdout - act.isql(switches=['-q', f'inet4://{act.db.db_path}'], input=sql_chk, connect_db=False) + act.isql(switches=['-q', f'inet://{act.db.db_path}'], input=sql_chk, connect_db=False) assert act.clean_stdout == act.clean_expected_stdout From 77848193e433e68964428c496efdd4e646a1ad9c Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Thu, 13 Jun 2024 16:54:39 +0300 Subject: [PATCH 0053/1064] Fixed bug #23 : QA could hung when stopping trace session --- src/firebird/qa/plugin.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/firebird/qa/plugin.py b/src/firebird/qa/plugin.py index 9b0d0f54..12aaa8a3 100644 --- a/src/firebird/qa/plugin.py +++ b/src/firebird/qa/plugin.py @@ -1340,12 +1340,10 @@ def __enter__(self) -> TraceSession: def __exit__(self, exc_type, exc_value, traceback) -> None: time.sleep(2) session = self.output.pop(0) - with self.act.connect_server() as srv: - srv.trace.stop(session_id=session) - self.stop_event.set() - self.trace_thread.join(5.0) - if self.trace_thread.is_alive(): - pytest.fail('Trace thread still alive') + self.stop_event.set() + self.trace_thread.join(5.0) + if self.trace_thread.is_alive(): + pytest.fail('Trace thread still alive') self.act.trace_log = self.output class ServerKeeper: From 79348425b5612434469ab6251cd61927595d37c9 Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Thu, 13 Jun 2024 17:12:49 +0300 Subject: [PATCH 0054/1064] Fixed bug #24 : QA could hung when starting trace session --- src/firebird/qa/plugin.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/firebird/qa/plugin.py b/src/firebird/qa/plugin.py index 9b0d0f54..97e140f3 100644 --- a/src/firebird/qa/plugin.py +++ b/src/firebird/qa/plugin.py @@ -1265,17 +1265,24 @@ def trace_thread(act: Action, b: Barrier, cfg: List[str], output: List[str], kee role: User role stop: Event used to stop the trace thread """ - with act.connect_server(encoding=encoding, encoding_errors=encoding_errors, - user=user, password=password) as srv: - output.append(srv.trace.start(config='\n'.join(cfg))) - b.wait() - while not stop.is_set(): - line = srv.readline_timed(1) - if line is not TIMEOUT: - if not line: - stop.set() - elif keep_log: - output.append(line) + connected = False + try: + with act.connect_server(encoding=encoding, encoding_errors=encoding_errors, + user=user, password=password) as srv: + output.append(srv.trace.start(config='\n'.join(cfg))) + b.wait() + connected = True + while not stop.is_set(): + line = srv.readline_timed(1) + if line is not TIMEOUT: + if not line: + stop.set() + elif keep_log: + output.append(line) + except: + if not connected: + b.wait() + raise class TraceSession: """Object to manage Firebird trace session. From c76e44a47eb29fef2a1fad0bb2e4aa4839616b0b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 14 Jun 2024 11:09:48 +0300 Subject: [PATCH 0055/1064] Added/Updated tests\bugs\core_5229_test.py: Added EDS with '[::1]' after fixed GH-8156 --- tests/bugs/core_5229_test.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_5229_test.py b/tests/bugs/core_5229_test.py index f2b44bfa..a3a69e44 100644 --- a/tests/bugs/core_5229_test.py +++ b/tests/bugs/core_5229_test.py @@ -14,15 +14,15 @@ Test should IMHO check IPv4/IPv6 availability on test host before runs inet6:// check. [13.06.2024] pzotov 1. Added check for ability to use IPv6. - 2. Attempt to specify explicitly IPv6 address "[::1]" in ES/EDS causes error: + 2. Attempt to specify explicitly IPv6 address "[::1]" in ES/EDS caused error: ======== Statement failed, SQLSTATE = 42000 External Data Source provider 'inet6://[' not found ======== - Sent report to Vlad et al, waiting for fix. - Currently no concrete address is specified in ES/EDS. - - Checked on 3.0.12.33744, 4.0.5.3103, 5.0.1.1411, 6.0.0.368 + It was fixed in gh-8156. + [14.06.2024] pzotov + Checked "on external 'inet6://[::1]/{act.db.db_path}'" after fixed GH-8156, builds: + 3.0.12.33757, 4.0.5.3112, 5.0.1.1416, 6.0.0.374 """ import pytest from firebird.qa import * @@ -109,10 +109,8 @@ def test_1(act: Action): set term ;^ commit; - -- since 27.10.2019: - -- inet6://[::1]/employee - -- connect 'inet6://[::1]/{act.db.db_path}'; - connect 'inet6://{act.db.db_path}'; + -- since 27.10.2019; checked again 13.06.2024 + connect 'inet6://[::1]/{act.db.db_path}'; select mon$remote_protocol as procotol_when_connect_from_isql from mon$attachments where mon$attachment_id = current_connection; @@ -123,8 +121,8 @@ def test_1(act: Action): begin for execute statement (stt) - --on external 'inet6://[::1]/{act.db.db_path}' -- currently fails with - on external 'inet6://{act.db.db_path}' + -- Failed before fix #8156 ("Can not specify concrete IPv6 address in ES/EDS connection string"): + on external 'inet6://[::1]/{act.db.db_path}' as user '{act.db.user}' password '{act.db.password}' into protocol_when_connect_by_es_eds do From 9c6c4990a8569c9dd1569625cd831448b93ea4c6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 16 Jun 2024 09:23:58 +0300 Subject: [PATCH 0056/1064] Added/Updated tests\bugs\core_5236_test.py: Plan for FB 5.x and 6.x changed since 28-may-2024, build 6.0.0.363 #95442. It was adjusted after talk with dimitr: must be the same for all FB versions --- tests/bugs/core_5236_test.py | 64 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/tests/bugs/core_5236_test.py b/tests/bugs/core_5236_test.py index 1a8dd9b2..296f35b4 100644 --- a/tests/bugs/core_5236_test.py +++ b/tests/bugs/core_5236_test.py @@ -12,10 +12,7 @@ -> Nested Loop Join (inner) <<<<<<< no filter of "DP_REGISTRO" table -> Table "DP_REGISTRO" Full Scan <<<<<<< after it was scanned -> Filter - -> Table "DP_RECIBO" Access By ID - -> Bitmap - -> Index "UNQ1_DP_RECIBO" Range Scan (partial match: 1/2) - + ... Plan AFTER fix (confirmed on 4.0.0.313): ... Select Expression @@ -23,11 +20,15 @@ -> Filter <<<<<<<<<<<<<<<<<<<<<<<<<<< EARLY FILTERING MUST BE HERE <<<<< -> Table "DP_REGISTRO" Full Scan -> Filter - -> Table "DP_RECIBO" Access By ID - -> Bitmap - -> Index "UNQ1_DP_RECIBO" Range Scan (partial match: 1/2) + ... JIRA: CORE-5236 FBTEST: bugs.core_5236 +NOTES: + [16.06.2024] pzotov + Plan for FB 5.x and 6.x changed since 28-may-2024, build 6.0.0.363 #95442. + It was adjusted after talk with dimitr: must be the same for all FB versions + (with only difference: 'Sub-query' at the top line for FB 5.x+). + Changed filler character for show padding ('#' --> '.'). """ import pytest @@ -68,7 +69,7 @@ #----------------------------------------------------------- -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped @@ -93,35 +94,36 @@ def test_1(act: Action, capsys): fb4x_expected_out = """ Select Expression - ####-> Filter - ########-> Filter - ############-> Table "DP_REGISTRO_OEST" Access By ID - ################-> Bitmap - ####################-> Index "UNQ1_DP_REGISTRO_OEST" Unique Scan + ....-> Filter + ........-> Filter + ............-> Table "DP_REGISTRO_OEST" Access By ID + ................-> Bitmap + ....................-> Index "UNQ1_DP_REGISTRO_OEST" Unique Scan Select Expression - ####-> Nested Loop Join (inner) - ########-> Filter - ############-> Table "DP_REGISTRO" Full Scan - ########-> Filter - ############-> Table "DP_RECIBO" Access By ID - ################-> Bitmap - ####################-> Index "UNQ1_DP_RECIBO" Range Scan (partial match: 1/2) + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "DP_REGISTRO" Full Scan + ........-> Filter + ............-> Table "DP_RECIBO" Access By ID + ................-> Bitmap + ....................-> Index "UNQ1_DP_RECIBO" Range Scan (partial match: 1/2) """ fb5x_expected_out = """ Sub-query - ####-> Filter - ########-> Filter - ############-> Table "DP_REGISTRO_OEST" Access By ID - ################-> Bitmap - ####################-> Index "UNQ1_DP_REGISTRO_OEST" Unique Scan + ....-> Filter + ........-> Filter + ............-> Table "DP_REGISTRO_OEST" Access By ID + ................-> Bitmap + ....................-> Index "UNQ1_DP_REGISTRO_OEST" Unique Scan Select Expression - ####-> Filter - ########-> Hash Join (inner) - ############-> Table "DP_RECIBO" Full Scan - ############-> Record Buffer (record length: 25) - ################-> Filter - ####################-> Table "DP_REGISTRO" Full Scan + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "DP_REGISTRO" Full Scan + ........-> Filter + ............-> Table "DP_RECIBO" Access By ID + ................-> Bitmap + ....................-> Index "UNQ1_DP_RECIBO" Range Scan (partial match: 1/2) """ with act.db.connect() as con: From f073668eb059e76cb44ff5402e8b30948c99c2ea Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 17 Jun 2024 15:55:17 +0300 Subject: [PATCH 0057/1064] Added/Updated tests\bugs\gh_7937_test.py: Reduced min_version to 5.0.1 after check on 5.0.1.1416-b4b3559. --- tests/bugs/gh_7937_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_7937_test.py b/tests/bugs/gh_7937_test.py index ba0307ce..e5fa59a3 100644 --- a/tests/bugs/gh_7937_test.py +++ b/tests/bugs/gh_7937_test.py @@ -10,6 +10,9 @@ Confirmed bug on 5.0.0.1305, 6.0.0.279 Checked on 6.0.0.286 -- all OK. Thanks to dimitr for providing simplest test case. + + [17.06.2024] pzotov + Reduced min_version to 5.0.1 after check on 5.0.1.1416-b4b3559. """ import pytest @@ -42,7 +45,7 @@ COUNT 1 """ -@pytest.mark.version('>=6.0.0') +@pytest.mark.version('>=5.0.1') def test_1(act: Action): act.expected_stdout = expected_stdout act.execute(combine_output = True) From 350e8410121aedcc8badb8327cf4d18349c94c66 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 18 Jun 2024 09:42:54 +0300 Subject: [PATCH 0058/1064] Added/Updated tests\bugs\gh_4723_incompressible_test.py: adjusted min_version --- tests/bugs/gh_4723_incompressible_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_4723_incompressible_test.py b/tests/bugs/gh_4723_incompressible_test.py index 1d1af1ed..839eadd0 100644 --- a/tests/bugs/gh_4723_incompressible_test.py +++ b/tests/bugs/gh_4723_incompressible_test.py @@ -67,7 +67,7 @@ db = db_factory(page_size = 8192, init = init_ddl, charset = 'win1251') act = python_act('db') -@pytest.mark.version('>=4.0') +@pytest.mark.version('>=5.0') def test_1(act: Action, capsys): act.gstat(switches=['-r', '-t', 'TEST', '-user', act.db.user, '-pass', act.db.password]) From 4e2dd4caaa31d95561ff621c14b434044ec26cdc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 20 Jun 2024 10:18:40 +0300 Subject: [PATCH 0059/1064] Added compressed .fbk needed for test bugs/gh_8161_test.py --- files/gh_8161.zip | Bin 0 -> 13221 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_8161.zip diff --git a/files/gh_8161.zip b/files/gh_8161.zip new file mode 100644 index 0000000000000000000000000000000000000000..5d95df07e1b757d2b363566076292f5d7b286c91 GIT binary patch literal 13221 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 literal 0 HcmV?d00001 From 08dcde41f4f70c389ccdb21b48b355c68f0856a1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 20 Jun 2024 10:19:16 +0300 Subject: [PATCH 0060/1064] Added/Updated tests\bugs\gh_8161_test.py: Confirmed bug/regression on 3.0.12.33735. Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374 --- tests/bugs/gh_8161_test.py | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/bugs/gh_8161_test.py diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py new file mode 100644 index 00000000..f64aac1d --- /dev/null +++ b/tests/bugs/gh_8161_test.py @@ -0,0 +1,98 @@ +#coding:utf-8 + +""" +ID: issue-8161 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8161 +TITLE: Cardinality estimation should use primary record versions only +DESCRIPTION: + Test must use .fbk file from core-5602. It was copied to separate file and packed into gh_8161.zip + We check explained plan of query (making 'padding' of every line with '.' character for preserving indentation). + Statistics is not checked. + Numeric suffixes of index names from RDB tables are suppressed because they can change in the future. + Also, we suppress output of rows with 'line NNN, column NNN' (FB 5.x+) because they have no matter in this test. +NOTES: + [20.06.2024] pzotov + Confirmed bug (regression) on 3.0.12.33735 (date of build: 09-mar-2024). + Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374 +""" +import zipfile +from pathlib import Path +import locale +import re + +import pytest +from firebird.qa import * + +db = db_factory() + +substitutions = [('INDEX_\\d+', 'INDEX_nn'), ('\\(?line \\d+, column \\d+\\)?', '')] + +act = python_act('db', substitutions = substitutions) +tmp_fbk = temp_file('gh_8161.tmp.fbk') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=3.0.12') +def test_1(act: Action, tmp_fbk: Path, capsys): + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_8161.zip', at = 'gh_8161.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + act.gbak(switches = ['-rep', str(tmp_fbk), act.db.db_path], combine_output = True, io_enc = locale.getpreferredencoding()) + print(act.stdout) # must be empty + + test_sql = """ + execute block as + declare relname varchar(32); + declare cnt int; + begin + for select X.RDB$RELATION_NAME + from RDB$RELATION_FIELDS X + where X.RDB$FIELD_SOURCE = 'BOOL_EMUL' + into :relname + do begin + select count(*) + from RDB$DEPENDENCIES DEP, RDB$PROCEDURES PRC + where DEP.RDB$DEPENDED_ON_NAME = :relname + AND DEP.RDB$FIELD_NAME = :relname + AND DEP.RDB$DEPENDED_ON_TYPE = 0 /* obj_relation */ + AND DEP.RDB$DEPENDENT_TYPE = 5 /* obj_procedure */ + AND DEP.RDB$DEPENDENT_NAME = PRC.RDB$PROCEDURE_NAME + AND PRC.RDB$PACKAGE_NAME IS NULL + into :cnt; + end + end + """ + + 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')]) ) + + expected_stdout = """ + Select Expression + ....-> Singularity Check + ........-> Aggregate + ............-> Nested Loop Join (inner) + ................-> Filter + ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_28" Range Scan (full match) + ................-> Filter + ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_21" Unique Scan + Select Expression + ....-> Filter + ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID + ............-> Bitmap + ................-> Index "RDB$INDEX_3" Range Scan (full match) + """ + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 86308b3ee8aaea43a67e0a818051b7ddef1bd94f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 20 Jun 2024 11:19:37 +0300 Subject: [PATCH 0061/1064] Added/Updated tests\bugs\gh_8161_test.py: added comments --- tests/bugs/gh_8161_test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py index f64aac1d..e293c96d 100644 --- a/tests/bugs/gh_8161_test.py +++ b/tests/bugs/gh_8161_test.py @@ -12,8 +12,13 @@ Also, we suppress output of rows with 'line NNN, column NNN' (FB 5.x+) because they have no matter in this test. NOTES: [20.06.2024] pzotov + Despite that we use 'clean' (i.e. just restored) DB, back-versions CAN exists there for system tables, + particularly (for this .fbk) - in rdb$dependencies and rdb$procedures. + For that test not only back-versions but also blobs and fragments matter. + See letters from dimitr and hvlad: 20.06.2024 10:36, 10:39. + Confirmed bug (regression) on 3.0.12.33735 (date of build: 09-mar-2024). - Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374 + Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374. """ import zipfile from pathlib import Path From 0618f10625a96e0a6a045c2dccee4f676c332eda Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 21 Jun 2024 02:36:49 +0300 Subject: [PATCH 0062/1064] Added/Updated tests\bugs\gh_4723_incompressible_test.py: dummy change to force all major versions to be checked again --- tests/bugs/gh_4723_incompressible_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_4723_incompressible_test.py b/tests/bugs/gh_4723_incompressible_test.py index 839eadd0..02f72c8c 100644 --- a/tests/bugs/gh_4723_incompressible_test.py +++ b/tests/bugs/gh_4723_incompressible_test.py @@ -18,7 +18,7 @@ Average record length: 32757.00, total records: 10000 Average unpacked length: 32766.00, compression ratio: 1.00 Pointer pages: 1, data page slots: 304 - Data pages: 304, average fill: 87% + Data pages: 304, average fill: 87%. Test assumes that values returned for 5.x will not be change in too wide range for several upcoming years in any order - see MIN_* and MAX_* thresholds. From 647b877d67c2b46b7ae7233d71da9338f5f374e9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 21 Jun 2024 11:11:46 +0300 Subject: [PATCH 0063/1064] Added/Updated tests\functional\replication\test_bugcheck_in_rw_replica_after_conflicting_insert.py: Added debug output if some goes wrong. Fixed stupid copy-paste code that can cause fail. Checked on 4.0.5.3112-d2e612c, 5.0.1.1416-b4b3559, 6.0.0.374-0097d28 --- ..._in_rw_replica_after_conflicting_insert.py | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py b/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py index 53be2f38..0c96bc1f 100644 --- a/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py +++ b/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py @@ -45,6 +45,7 @@ its previous code (i.e. to keep the way it is). Checked on 6.0.0.299 b1ba859 (SS/CS). + Checked on 4.0.5.3112-d2e612c, 5.0.1.1416-b4b3559, 6.0.0.374-0097d28 """ import os import shutil @@ -62,6 +63,7 @@ repl_settings = QA_GLOBALS['replication'] MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) +MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = 20 MAIN_DB_ALIAS = repl_settings['main_db_alias'] REPL_DB_ALIAS = repl_settings['repl_db_alias'] RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) @@ -208,12 +210,12 @@ def check_repl_log( act_db_main: Action, max_allowed_time_for_wait, expected_out cur.execute("select rdb$get_context('SYSTEM','REPLICATION_SEQUENCE') from rdb$database") last_generated_repl_segment = int(cur.fetchone()[0]) - p_info_line_02 = re.compile('Added \\d+ segment\\(s\\) to the queue') - p_info_line_02 = re.compile('Record being inserted .* exists, updating instead') - p_info_line_03 = re.compile(f'Segment {last_generated_repl_segment} \\(\\d+ bytes\\) is replicated .* deleting') - info_01_lines_unq = set() - info_02_lines_unq = set() - info_03_lines_unq = set() + ptn_repl_chk_01 = re.compile('Added \\d+ segment\\(s\\) to the queue') + ptn_repl_chk_02 = re.compile('Record being inserted .* exists, updating instead') + ptn_repl_chk_03 = re.compile(f'Segment {last_generated_repl_segment} \\(\\d+ bytes\\) is replicated .* deleting') + line_match_01 = set() + line_match_02 = set() + line_match_03 = set() found_all = False @@ -228,18 +230,18 @@ def check_repl_log( act_db_main: Action, max_allowed_time_for_wait, expected_out for k,diff_line in enumerate(diff_data): expr = f"select {k} as iter, current_timestamp, q'<{diff_line}>' from rdb$database" - if p_info_line_02.search(diff_line): - info_01_lines_unq.add(k) - expr = f"select {k} as info_01_line, q'<{diff_line}>' as info_01_text, {len(info_01_lines_unq)} as info_01_found, {len(info_02_lines_unq)} as info_02_found, {len(info_03_lines_unq)} as info_03_found from rdb$database" - if p_info_line_02.search(diff_line): - info_02_lines_unq.add(k) - expr = f"select {k} as info_02_line, q'<{diff_line}>' as info_02_text, {len(info_02_lines_unq)} as info_02_found, {len(info_02_lines_unq)} as info_02_found, {len(info_03_lines_unq)} as info_03_found from rdb$database" - if p_info_line_02.search(diff_line): - info_03_lines_unq.add(k) - expr = f"select {k} as info_03_line, q'<{diff_line}>' as info_03_text, {len(info_03_lines_unq)} as info_03_found, {len(info_02_lines_unq)} as info_02_found, {len(info_03_lines_unq)} as info_03_found from rdb$database" + if ptn_repl_chk_01.search(diff_line): + line_match_01.add(k) + expr = f"select {k} as info_01_line, q'<{diff_line}>' as info_01_text, {len(line_match_01)} as info_01_found, {len(line_match_02)} as info_02_found, {len(line_match_03)} as info_03_found from rdb$database" + if ptn_repl_chk_02.search(diff_line): + line_match_02.add(k) + expr = f"select {k} as info_02_line, q'<{diff_line}>' as info_02_text, {len(line_match_02)} as info_02_found, {len(line_match_02)} as info_02_found, {len(line_match_03)} as info_03_found from rdb$database" + if ptn_repl_chk_03.search(diff_line): + line_match_03.add(k) + expr = f"select {k} as info_03_line, q'<{diff_line}>' as info_03_text, {len(line_match_03)} as info_03_found, {len(line_match_02)} as info_02_found, {len(line_match_03)} as info_03_found from rdb$database" # _dummy_ = cur.execute(expr).fetchone() - if len(info_03_lines_unq) >= 1 and len(info_03_lines_unq) >= 1 and len(info_03_lines_unq) >= 1: + if len(line_match_01) >= 1 and len(line_match_02) >= 1 and len(line_match_03) >= 1: found_all = True break @@ -247,7 +249,11 @@ def check_repl_log( act_db_main: Action, max_allowed_time_for_wait, expected_out break if not found_all: - result = f'UNEXPECTED: messages about replicated segment {last_generated_repl_segment} did not appear for {max_allowed_time_for_wait} seconds.' + unexp_msg = f'UNEXPECTED: messages about replicated segment {last_generated_repl_segment} did not appear for {max_allowed_time_for_wait} seconds.' + repllog_diff = '\n'.join( [ ('%4d ' %i) + r for i,r in enumerate(diff_data) ] ) + checked_ptn_msg = f'{ptn_repl_chk_01=}\n{ptn_repl_chk_02=}\n{ptn_repl_chk_03=}' + lines_match_msg = f'{line_match_01=}; {line_match_02=}; {line_match_03=}; ' + result = '\n'.join( [unexp_msg, 'Lines in replication.log:', repllog_diff, 'Checked patterns:', checked_ptn_msg, 'Lines NN that match patterns:', lines_match_msg] ) else: result = expected_output_str From d37a99fc5afa6726f43830353d35d3a6b53a85d3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 21 Jun 2024 11:12:42 +0300 Subject: [PATCH 0064/1064] Added/Updated tests\functional\replication\test_bugcheck_in_rw_replica_after_conflicting_insert.py: Removed hard-coded max_wait that was added temporary for debug. --- .../test_bugcheck_in_rw_replica_after_conflicting_insert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py b/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py index 0c96bc1f..538aa7b0 100644 --- a/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py +++ b/tests/functional/replication/test_bugcheck_in_rw_replica_after_conflicting_insert.py @@ -63,7 +63,7 @@ repl_settings = QA_GLOBALS['replication'] MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) -MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = 20 + MAIN_DB_ALIAS = repl_settings['main_db_alias'] REPL_DB_ALIAS = repl_settings['repl_db_alias'] RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) From ee1d83625e8f3d859db5c0b94dfce14834e5fb16 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 21 Jun 2024 13:50:10 +0300 Subject: [PATCH 0065/1064] Added/Updated tests\functional\replication\test_invalid_msg_if_target_db_has_no_replica_flag.py: Partially re-implemented - see notes. Checked on Windows, 4.0.5.3112-d2e612c, 5.0.1.1416-b4b3559, 6.0.0.374-0097d28 (SS and CS). --- ...id_msg_if_target_db_has_no_replica_flag.py | 224 +++++++++--------- 1 file changed, 106 insertions(+), 118 deletions(-) diff --git a/tests/functional/replication/test_invalid_msg_if_target_db_has_no_replica_flag.py b/tests/functional/replication/test_invalid_msg_if_target_db_has_no_replica_flag.py index 811741e8..188d1053 100644 --- a/tests/functional/replication/test_invalid_msg_if_target_db_has_no_replica_flag.py +++ b/tests/functional/replication/test_invalid_msg_if_target_db_has_no_replica_flag.py @@ -51,7 +51,12 @@ [23.11.2023] pzotov Make final SWEEP optional, depending on setting RUN_SWEEP_AT_END - see $QA_ROOT/files/test_config.ini. - Checked on Windows, 6.0.0.193, 5.0.0.1304, 4.0.5.3042 (SS/CS for all). + [21.06.2024] pzotov + Partially re-implemented: + * full replacement of func check_repl_log; its new name = 'wait_for_repl_err' + * added code for simplifying debug; + * removed check of capsys content from most places (replaced with comparison of result with empty string). + Checked on Windows, 4.0.5.3112-d2e612c, 5.0.1.1416-b4b3559, 6.0.0.374-0097d28 (SS and CS). """ import os import shutil @@ -72,6 +77,7 @@ MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG = int(repl_settings['max_time_for_wait_segment_in_log']) MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) + MAIN_DB_ALIAS = repl_settings['main_db_alias'] REPL_DB_ALIAS = repl_settings['repl_db_alias'] RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) @@ -190,38 +196,19 @@ def reset_replication(act_db_main, act_db_repl, db_main_file, db_repl_file): #-------------------------------------------- -def check_repl_log( act_db_main: Action, max_allowed_time_for_wait, prefix_msg = '' ): +def wait_for_repl_err( act_db_main: Action, replold_lines, max_allowed_time_for_wait): replication_log = act_db_main.home_dir / 'replication.log' - replold_lines = [] - with open(replication_log, 'r') as f: - replold_lines = f.readlines() - - with act_db_main.db.connect(no_db_triggers = True) as con: - with con.cursor() as cur: - cur.execute("select rdb$get_context('SYSTEM','REPLICATION_SEQUENCE') from rdb$database") - last_generated_repl_segment = cur.fetchone()[0] - - # VERBOSE: Segment 1 (2582 bytes) is replicated in 1 second(s), deleting the file - # VERBOSE: Segment 2 (200 bytes) is replicated in 82 ms, deleting the file - p_successfully_replicated = re.compile( f'\\+\\s+verbose:\\s+segment\\s+{last_generated_repl_segment}\\s+\\(\\d+\\s+bytes\\)\\s+is\\s+replicated.*deleting', re.IGNORECASE) - - # VERBOSE: Segment 16 replication failure at offset 33628 - p_replication_failure = re.compile('segment\\s+\\d+\\s+replication\\s+failure', re.IGNORECASE) - # ERROR: Database is not in the replica mode p_database_not_replica = re.compile('ERROR:\\s+Database.* not.* replica', re.IGNORECASE) found_required_message = False - found_replfail_message = False - found_common_error_msg = False - + found_required_line = '' for i in range(0,max_allowed_time_for_wait): time.sleep(1) - # Get content of fb_home/replication.log _after_ isql finish: with open(replication_log, 'r') as f: diff_data = unified_diff( replold_lines, @@ -229,39 +216,35 @@ def check_repl_log( act_db_main: Action, max_allowed_time_for_wait, prefix_msg = ) for k,d in enumerate(diff_data): - if p_successfully_replicated.search(d): - # We FOUND phrase "VERBOSE: Segment ... is replicated ..." in the replication log. - # This is expected success, break! - print( (prefix_msg + ' ' if prefix_msg else '') + f'FOUND message about replicated segment N {last_generated_repl_segment}.' ) - found_required_message = True - break - - if p_replication_failure.search(d): - print( (prefix_msg + ' ' if prefix_msg else '') + 'SEGMENT_FAILURE: ' + d ) - found_replfail_message = True - break - if p_database_not_replica.search(d): - print( (prefix_msg + ' ' if prefix_msg else '') + 'EXPECTED_NOT_REPL') found_required_message = True break - if 'ERROR:' in d: - print( (prefix_msg + ' ' if prefix_msg else '') + 'COMMON_FAILURE: ' + d ) - found_common_error_msg = True - break - - if found_required_message or found_replfail_message or found_common_error_msg: + if found_required_message: break if not found_required_message: - print(f'UNEXPECTED RESULT: no message about replicating segment N {last_generated_repl_segment} for {max_allowed_time_for_wait} seconds.') + # ACHTUNG! This looks weird but we have to either re-read replication log now or wait at least seconds + # if we want to see FULL (actual) content of this log! Otherwise last part of log will be missed. I have no explanations for that :( + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + unexp_msg = f"Expected ERROR message was not found for {max_allowed_time_for_wait} seconds." + repllog_diff = '\n'.join( ( ('%4d ' %i) + r.rstrip() for i,r in enumerate(diff_data) ) ) + result = '\n'.join( (unexp_msg, 'Lines in replication.log:', repllog_diff) ) + else: + result = '' + + return result #-------------------------------------------- def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + result = '' retcode = 1; ready_to_check = False if ddl_ready_query: @@ -279,48 +262,49 @@ def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', i else: ready_to_check = True - if not ready_to_check: - print( f'UNEXPECTED. Initial check query did not return any rows for {max_allowed_time_for_wait} seconds.' ) - print('Initial check query:') - print(ddl_ready_query) - return - - final_check_pass = False - if isql_check_script: - retcode = 0 - for i in range(max_allowed_time_for_wait): - a.reset() - a.expected_stdout = replica_expected_out - a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) - - if a.return_code: - # "Token unknown", "Name longer than database column size" etc: we have to - # immediately break from this loop because isql_check_script is incorrect! - break - - if a.clean_stdout == a.clean_expected_stdout: - final_check_pass = True - break - if i < max_allowed_time_for_wait-1: - time.sleep(1) - - if not final_check_pass: - print(f'UNEXPECTED. Final check query did not return expected dataset for {max_allowed_time_for_wait} seconds.') - print('Final check query:') - print(isql_check_script) - print('Expected output:') - print(a.clean_expected_stdout) - print('Actual output:') - print(a.clean_stdout) - print(f'ISQL return_code={a.return_code}') - print(f'Waited for {i} seconds') - - a.reset() + msg = f'UNEXPECTED. Check query did not return any rows for {max_allowed_time_for_wait} seconds.' + if not ready_to_check: + result = '\n'.join((msg, 'ddl_ready_query:', ddl_ready_query)) else: - final_check_pass = True + final_check_pass = False + if isql_check_script: + retcode = 0 + for i in range(max_allowed_time_for_wait): + a.reset() + a.expected_stdout = replica_expected_out + a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) + + if a.return_code: + # "Token unknown", "Name longer than database column size" etc: we have to + # immediately break from this loop because isql_check_script is incorrect! + break + + if a.clean_stdout == a.clean_expected_stdout: + final_check_pass = True + break + if i < max_allowed_time_for_wait-1: + time.sleep(1) + + if not final_check_pass: + + result = '\n'.join( + ( msg + ,'Final check query:' + ,isql_check_script + ,'Expected output:' + ,a.clean_expected_stdout + ,'Actual output:' + ,a.clean_stdout + ,f'ISQL return_code={a.return_code}' + ,f'Waited for {i} seconds' + ) + ) + a.reset() + else: + final_check_pass = True - return + return result #-------------------------------------------- @@ -330,6 +314,7 @@ def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): # remove all DB objects (tables, views, ...): # db_main_meta, db_repl_meta = '', '' + result = '' for a in (act_db_main,act_db_repl): if a == act_db_main: sql_clean = (a.files_dir / 'drop-all-db-objects.sql').read_text() @@ -342,7 +327,8 @@ def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): if a.clean_stdout == a.clean_expected_stdout: a.reset() else: - print(a.clean_expected_stdout) + result = a.clean_stdout + # print(a.clean_stdout) a.reset() break @@ -388,10 +374,10 @@ def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): ############################################################################## ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### ############################################################################## - watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + result = watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) # Must be EMPTY: - print(capsys.readouterr().out) + #print(capsys.readouterr().out) db_main_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') else: @@ -407,14 +393,17 @@ def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): # a.gfix(switches=['-sweep', a.db.dsn]) - # Final point: metadata must become equal: - # - diff_meta = ''.join(unified_diff( \ - [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], - [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) - ) - # Must be EMPTY: - print(diff_meta) + if result == '': + # Final point: metadata must become equal: + # + diff_meta = ''.join(unified_diff( \ + [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], + [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) + ) + # Must be EMPTY: + return diff_meta + else: + return result #-------------------------------------------- @@ -424,9 +413,14 @@ def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): def test_1(act_db_main: Action, act_db_repl: Action, capsys): db_info = {} - out_prep, out_main, out_drop, out_reset = '', '', '', '' - smth_failed = None + out_prep = out_main = out_back = out_drop = out_reset = '' + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + replication_log = act_db_main.home_dir / 'replication.log' + replold_lines = [] + with open(replication_log, 'r') as f: + replold_lines = f.readlines() + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Obtain full path + filename for DB_MAIN and DB_REPL aliases. # NOTE: we must NOT use 'a.db.db_path' for ALIASED databases! @@ -456,6 +450,10 @@ def test_1(act_db_main: Action, act_db_repl: Action, capsys): insert into test(id, x) values(1, 100); commit; ''' + + # Applying script on master but replica will NOT accept it because its replication mode = NONE. + # Message "ERROR: Database is not in the replica mode" must appear after this ISQL call: + # act_db_main.isql(switches=['-q'], input = sql_init, combine_output = True) out_prep = act_db_main.clean_stdout act_db_main.reset() @@ -463,29 +461,22 @@ def test_1(act_db_main: Action, act_db_repl: Action, capsys): if out_prep: pass else: - try: - # During next seconds message - # "ERROR: Database is not in the replica mode" must appear in replication log: - - act_db_main.expected_stdout = 'EXPECTED_NOT_REPL' - ############################################################### - ### W A I T F O R E R R O R I N R E P L . L O G ### - ############################################################### - check_repl_log( act_db_main, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG, '' ) - act_db_main.stdout = capsys.readouterr().out - assert act_db_main.clean_stdout == act_db_main.clean_expected_stdout - act_db_main.reset() + # During next seconds message + # "ERROR: Database is not in the replica mode" must appear in replication log - #--------------------------------------------------- + ################################################################## + ### W A I T F O R E R R O R I N R E P L . L O G ### + ################################################################## + out_main = wait_for_repl_err( act_db_main, replold_lines, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG) + try: # Return db_repl mode to 'read-only' (as it was before this test) # and wait after it for seconds # for previously created segment be replicated: with act_db_repl.connect_server() as srv: srv.database.set_replica_mode(database = act_db_repl.db.db_path, mode = ReplicaMode.READ_ONLY) - # Query to be used for check that all DB objects present in replica (after last DML statement completed on master DB): ddl_ready_query = "select 1 from rdb$relations where rdb$relation_name = upper('test')" @@ -511,22 +502,16 @@ def test_1(act_db_main: Action, act_db_repl: Action, capsys): ############################################################################## ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### ############################################################################## - watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query, isql_check_script, isql_expected_out) - - # Must be EMPTY: - out_main = capsys.readouterr().out + out_back = watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query, isql_check_script, isql_expected_out) except Exception as e: - out_main = e.__str__() - - - drop_db_objects(act_db_main, act_db_repl, capsys) + out_back = e.__str__() # Must be EMPTY: - out_drop = capsys.readouterr().out + out_drop = drop_db_objects(act_db_main, act_db_repl, capsys) - if [ x for x in (out_prep, out_main, out_drop) if x.strip() ]: + if [ x for x in (out_prep, out_main, out_back, out_drop) if x.strip() ]: # We have a problem either with DDL/DML or with dropping DB objects. # First, we have to RECREATE both master and slave databases # (otherwise further execution of this test or other replication-related tests most likely will fail): @@ -541,6 +526,9 @@ def test_1(act_db_main: Action, act_db_repl: Action, capsys): if out_main.strip(): print('out_main:') print(out_main) + if out_back.strip(): + print('out_back:') + print(out_back) if out_drop.strip(): print('out_drop:') print(out_drop) From 2a6320b8b43576f5afab7268678e6547f2374832 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 9 Jul 2024 15:04:16 +0300 Subject: [PATCH 0066/1064] Added/Updated tests\bugs\core_5685_test.py: Added item to substitutions related to 'port detached' message that raises in dev build. --- tests/bugs/core_5685_test.py | 426 ++++++++++++++++++----------------- 1 file changed, 218 insertions(+), 208 deletions(-) diff --git a/tests/bugs/core_5685_test.py b/tests/bugs/core_5685_test.py index c53fd123..8fa3a885 100644 --- a/tests/bugs/core_5685_test.py +++ b/tests/bugs/core_5685_test.py @@ -1,208 +1,218 @@ -#coding:utf-8 - -""" -ID: issue-5951 -ISSUE: 5951 -TITLE: Sometime it is impossible to cancel/kill connection executing external query -DESCRIPTION: - Problem did appear when host "A" established connection to host "B" but could not get completed reply from this "B". - This can be emulated by following steps: - 1. We establich new remote connection to the same database using EDS mechanism and supply completely new ROLE to force new attachment be created; - 2. Within this EDS we do query to selectable procedure (with name 'sp_unreachable') which surely will not produce any result. - Bogon IP '192.0.2.2' is used in order to make this SP hang for sufficient time (on Windows it is about 20, on POSIX - about 44 seconds). - Steps 1 and 2 are implemented by asynchronous call of ISQL: we must have ability to kill its process after. - When this 'hanging ISQL' is launched, we wait 1..2 seconds and run one more ISQL, which has mission to KILL all attachments except his own. - This ISQL session is named 'killer', and it writes result of actions to log. - This "killer-ISQL" does TWO iterations with the same code which looks like 'select ... from mon$attachments' and 'delete from mon$attachments'. - First iteration must return data of 'hanging ISQL' and also this session must be immediately killed. - Second iteration must NOT return any data - and this is main check in this test. - - For builds which had bug (before 25.12.2017) one may see that second iteration STILL RETURNS the same data as first one: - ==== - ITERATION_NO 1 - HANGING_ATTACH_CONNECTION 1 - HANGING_ATTACH_PROTOCOL TCP - HANGING_STATEMENT_STATE 1 - HANGING_STATEMENT_BLOB_ID 0:3 - select * from sp_get_data - Records affected: 1 - - ITERATION_NO 2 - HANGING_ATTACH_CONNECTION 1 - HANGING_ATTACH_PROTOCOL TCP - HANGING_STATEMENT_STATE 1 - HANGING_STATEMENT_BLOB_ID 0:1 - select * from sp_get_data - Records affected: 1 - ==== - (expected: all fields in ITER #2 must be NULL) -JIRA: CORE-5685 -FBTEST: bugs.core_5685 -NOTES: - [06.10.2022] pzotov - Fails on Linux when run in 'batch' mode (i.e. when pytest has to perform the whole tests set). - Can not reproduce fail when run this test 'separately': it passes, but lasts too longm, ~130 s. - Test will be re-implemented. - DEFERRED. -""" -import platform -import pytest -import re -import subprocess -import time -from pathlib import Path -from firebird.qa import * -from firebird.driver import ShutdownMode, ShutdownMethod - -substitutions = [('.*After line.*', ''), ('.*Data source.*', '.*Data source'), - ('.*HANGING_STATEMENT_BLOB_ID.*', '')] - -init_script = """ - create sequence g; - commit; - set term ^; - create or alter procedure sp_unreachable returns( unreachable_address varchar(50) ) as - begin - for - execute statement ('select mon$remote_address from mon$attachments a where a.mon$attachment_id = current_connection') - on external '192.0.2.2:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user 'SYSDBA' password 'masterkey' role left(replace( uuid_to_char(gen_uuid()), '-', ''), 31) - into unreachable_address - do - suspend; - end - ^ - - create or alter procedure sp_get_data returns( unreachable_address varchar(50) ) as - begin - for - execute statement ('select u.unreachable_address from sp_unreachable as u') - on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user 'SYSDBA' password 'masterkey' role left(replace( uuid_to_char(gen_uuid()), '-', ''), 31) - into unreachable_address - do - suspend; - end - ^ - set term ;^ - commit; -""" - -db = db_factory(init=init_script) - -act = python_act('db', substitutions=substitutions) - -expected_stdout = """ - HANGED ATTACH, STDOUT: Records affected: 0 - HANGED ATTACH, STDERR: Statement failed, SQLSTATE = 42000 - HANGED ATTACH, STDERR: Execute statement error at isc_dsql_fetch : - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: Statement : select u.unreachable_address from sp_unreachable as u - .*Data source - HANGED ATTACH, STDERR: -At procedure 'SP_GET_DATA' line: 3, col: 9 - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - KILLER ATTACH, STDOUT: ITERATION_NO 1 - KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION 1 - KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL TCP - KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE 1 - KILLER ATTACH, STDOUT: select * from sp_get_data - KILLER ATTACH, STDOUT: Records affected: 1 - KILLER ATTACH, STDOUT: ITERATION_NO 2 - KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION - KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL - KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE - KILLER ATTACH, STDOUT: Records affected: 0 -""" - - -kill_script = """ - set list on; - set blob all; - select gen_id(g,1) as ITERATION_NO from rdb$database; - commit; - - select - sign(a.mon$attachment_id) as hanging_attach_connection - ,left(a.mon$remote_protocol,3) as hanging_attach_protocol - ,s.mon$state as hanging_statement_state - ,s.mon$sql_text as hanging_statement_blob_id - from rdb$database d - left join mon$attachments a on a.mon$remote_process containing 'isql' - -- do NOT use, field not existed in 2.5.x: and a.mon$system_flag is distinct from 1 - and a.mon$attachment_id is distinct from current_connection - left join mon$statements s on - a.mon$attachment_id = s.mon$attachment_id - and s.mon$state = 1 -- 4.0 Classic: 'SELECT RDB$MAP_USING, RDB$MAP_PLUGIN, ... FROM RDB$AUTH_MAPPING', mon$state = 0 - ; - - set count on; - delete from mon$attachments a - where - a.mon$attachment_id <> current_connection - and a.mon$remote_process containing 'isql' - ; - commit; -""" - -hang_script = temp_file('hang_script.sql') -hang_stdout = temp_file('hang_script.out') -hang_stderr = temp_file('hang_script.err') - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.es_eds -@pytest.mark.version('>=3.0.3') -def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path, - capsys): - hang_script.write_text('set list on; set count on; select * from sp_get_data;') - pattern_for_failed_statement = re.compile('Statement failed, SQLSTATE = (08006|08003)') - pattern_for_connection_close = re.compile('(Error (reading|writing) data (from|to) the connection)|(connection shutdown)') - pattern_for_ignored_messages = re.compile('(-send_packet/send)|(-Killed by database administrator.)') - killer_output = [] - # - with open(hang_stdout, mode='w') as hang_out, open(hang_stderr, mode='w') as hang_err: - p_hang_sql = subprocess.Popen([act.vars['isql'], '-i', str(hang_script), - '-user', act.db.user, - '-password', act.db.password, act.db.dsn], - stdout=hang_out, stderr=hang_err) - try: - time.sleep(4) - for i in range(2): - act.reset() - act.isql(switches=[], input=kill_script) - killer_output.append(act.stdout) - finally: - p_hang_sql.terminate() - # Ensure that database is not busy - with act.connect_server() as srv: - srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, - method=ShutdownMethod.FORCED, timeout=0) - time.sleep(2) - srv.database.bring_online(database=act.db.db_path) - # - output = [] - for line in hang_stdout.read_text().splitlines(): - if line.strip(): - output.append(f'HANGED ATTACH, STDOUT: {line}') - for line in hang_stderr.read_text().splitlines(): - if line.strip(): - if pattern_for_ignored_messages.search(line): - continue - elif pattern_for_failed_statement.search(line): - msg = '' - elif pattern_for_connection_close.search(line): - msg = '' - else: - msg = line - output.append(f'HANGED ATTACH, STDERR: {msg}') - for step in killer_output: - for line in act.clean_string(step).splitlines(): - if line.strip(): - output.append(f"KILLER ATTACH, STDOUT: {' '.join(line.split())}") - # Check - act.reset() - act.expected_stdout = expected_stdout - act.stdout = '\n'.join(output) - assert act.clean_stdout == act.clean_expected_stdout +#coding:utf-8 + +""" +ID: issue-5951 +ISSUE: 5951 +TITLE: Sometime it is impossible to cancel/kill connection executing external query +DESCRIPTION: + Problem did appear when host "A" established connection to host "B" but could not get completed reply from this "B". + This can be emulated by following steps: + 1. We establich new remote connection to the same database using EDS mechanism and supply completely new ROLE to force new attachment be created; + 2. Within this EDS we do query to selectable procedure (with name 'sp_unreachable') which surely will not produce any result. + Bogon IP '192.0.2.2' is used in order to make this SP hang for sufficient time (on Windows it is about 20, on POSIX - about 44 seconds). + Steps 1 and 2 are implemented by asynchronous call of ISQL: we must have ability to kill its process after. + When this 'hanging ISQL' is launched, we wait 1..2 seconds and run one more ISQL, which has mission to KILL all attachments except his own. + This ISQL session is named 'killer', and it writes result of actions to log. + This "killer-ISQL" does TWO iterations with the same code which looks like 'select ... from mon$attachments' and 'delete from mon$attachments'. + First iteration must return data of 'hanging ISQL' and also this session must be immediately killed. + Second iteration must NOT return any data - and this is main check in this test. + + For builds which had bug (before 25.12.2017) one may see that second iteration STILL RETURNS the same data as first one: + ==== + ITERATION_NO 1 + HANGING_ATTACH_CONNECTION 1 + HANGING_ATTACH_PROTOCOL TCP + HANGING_STATEMENT_STATE 1 + HANGING_STATEMENT_BLOB_ID 0:3 + select * from sp_get_data + Records affected: 1 + + ITERATION_NO 2 + HANGING_ATTACH_CONNECTION 1 + HANGING_ATTACH_PROTOCOL TCP + HANGING_STATEMENT_STATE 1 + HANGING_STATEMENT_BLOB_ID 0:1 + select * from sp_get_data + Records affected: 1 + ==== + (expected: all fields in ITER #2 must be NULL) +JIRA: CORE-5685 +FBTEST: bugs.core_5685 +NOTES: + [06.10.2022] pzotov + Fails on Linux when run in 'batch' mode (i.e. when pytest has to perform the whole tests set). + Can not reproduce fail when run this test 'separately': it passes, but lasts too longm, ~130 s. + Test will be re-implemented. + DEFERRED. + [09.07.2024] pzotov + Added item to substitutions related to 'port detached' message that raises in dev build. + Fixed wrong logic because of missed indentation, see hang_stderr. +""" +import platform +import pytest +import re +import subprocess +import time +from pathlib import Path +from firebird.qa import * +from firebird.driver import ShutdownMode, ShutdownMethod + +substitutions = [ ('.*After line.*', '') + ,('.*Data source.*', '.*Data source') + ,('.*HANGING_STATEMENT_BLOB_ID.*', '') + ,('.*-port detached', '') + ] + +init_script = """ + create sequence g; + commit; + set term ^; + create or alter procedure sp_unreachable returns( unreachable_address varchar(50) ) as + begin + for + execute statement ('select mon$remote_address from mon$attachments a where a.mon$attachment_id = current_connection') + on external '192.0.2.2:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user 'SYSDBA' password 'masterkey' role left(replace( uuid_to_char(gen_uuid()), '-', ''), 31) + into unreachable_address + do + suspend; + end + ^ + + create or alter procedure sp_get_data returns( unreachable_address varchar(50) ) as + begin + for + execute statement ('select u.unreachable_address from sp_unreachable as u') + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user 'SYSDBA' password 'masterkey' role left(replace( uuid_to_char(gen_uuid()), '-', ''), 31) + into unreachable_address + do + suspend; + end + ^ + set term ;^ + commit; +""" + +db = db_factory(init=init_script) + +act = python_act('db', substitutions=substitutions) + +expected_stdout = """ + HANGED ATTACH, STDOUT: Records affected: 0 + HANGED ATTACH, STDERR: Statement failed, SQLSTATE = 42000 + HANGED ATTACH, STDERR: Execute statement error at isc_dsql_fetch : + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: Statement : select u.unreachable_address from sp_unreachable as u + .*Data source + HANGED ATTACH, STDERR: -At procedure 'SP_GET_DATA' line: 3, col: 9 + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + KILLER ATTACH, STDOUT: ITERATION_NO 1 + KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION 1 + KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL TCP + KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE 1 + KILLER ATTACH, STDOUT: select * from sp_get_data + KILLER ATTACH, STDOUT: Records affected: 1 + KILLER ATTACH, STDOUT: ITERATION_NO 2 + KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION + KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL + KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE + KILLER ATTACH, STDOUT: Records affected: 0 +""" + + +kill_script = """ + set list on; + set blob all; + select gen_id(g,1) as ITERATION_NO from rdb$database; + commit; + + select + sign(a.mon$attachment_id) as hanging_attach_connection + ,left(a.mon$remote_protocol,3) as hanging_attach_protocol + ,s.mon$state as hanging_statement_state + ,s.mon$sql_text as hanging_statement_blob_id + from rdb$database d + left join mon$attachments a on a.mon$remote_process containing 'isql' + -- do NOT use, field not existed in 2.5.x: and a.mon$system_flag is distinct from 1 + and a.mon$attachment_id is distinct from current_connection + left join mon$statements s on + a.mon$attachment_id = s.mon$attachment_id + and s.mon$state = 1 -- 4.0 Classic: 'SELECT RDB$MAP_USING, RDB$MAP_PLUGIN, ... FROM RDB$AUTH_MAPPING', mon$state = 0 + ; + + set count on; + delete from mon$attachments a + where + a.mon$attachment_id <> current_connection + and a.mon$remote_process containing 'isql' + ; + commit; +""" + +hang_script = temp_file('hang_script.sql') +hang_stdout = temp_file('hang_script.out') +hang_stderr = temp_file('hang_script.err') + +@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') +@pytest.mark.es_eds +@pytest.mark.version('>=3.0.3') +def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path, + capsys): + hang_script.write_text('set list on; set count on; select * from sp_get_data;') + pattern_for_failed_statement = re.compile('Statement failed, SQLSTATE = (08006|08003)') + pattern_for_connection_close = re.compile('(Error (reading|writing) data (from|to) the connection)|(connection shutdown)') + pattern_for_ignored_messages = re.compile('(-send_packet/send)|(-Killed by database administrator.)') + killer_output = [] + # + with open(hang_stdout, mode='w') as hang_out, open(hang_stderr, mode='w') as hang_err: + p_hang_sql = subprocess.Popen([act.vars['isql'], '-i', str(hang_script), + '-user', act.db.user, + '-password', act.db.password, act.db.dsn], + stdout=hang_out, stderr=hang_err) + try: + time.sleep(4) + for i in range(2): + act.reset() + act.isql(switches=[], input=kill_script) + killer_output.append(act.stdout) + finally: + p_hang_sql.terminate() + # Ensure that database is not busy + with act.connect_server() as srv: + srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + time.sleep(2) + srv.database.bring_online(database=act.db.db_path) + # + output = [] + for line in hang_stdout.read_text().splitlines(): + if line.strip(): + output.append(f'HANGED ATTACH, STDOUT: {line}') + for line in hang_stderr.read_text().splitlines(): + if line.strip(): + msg = '' + if pattern_for_ignored_messages.search(line): + continue + elif pattern_for_failed_statement.search(line): + msg = '' + elif pattern_for_connection_close.search(line): + msg = '' + else: + msg = line + + if msg.strip(): + output.append(f'HANGED ATTACH, STDERR: {msg}') + + for step in killer_output: + for line in act.clean_string(step).splitlines(): + if line.strip(): + output.append(f"KILLER ATTACH, STDOUT: {' '.join(line.split())}") + + act.reset() + act.expected_stdout = expected_stdout + act.stdout = '\n'.join(output) + assert act.clean_stdout == act.clean_expected_stdout From 19514b3aeabd0947ed2bb8d9dea657c326ef4333 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 10 Jul 2024 12:03:40 +0300 Subject: [PATCH 0067/1064] Added/Updated tests\bugs\gh_7980_test.py: Checked on 6.0.0.386 --- tests/bugs/gh_7980_test.py | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/bugs/gh_7980_test.py diff --git a/tests/bugs/gh_7980_test.py b/tests/bugs/gh_7980_test.py new file mode 100644 index 00000000..657c5031 --- /dev/null +++ b/tests/bugs/gh_7980_test.py @@ -0,0 +1,62 @@ +#coding:utf-8 + +""" +ID: issue-7980 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7980 +TITLE: Option for GEN_UUID to generate v7 UUID +DESCRIPTION: + Test verifies: + * ability to call function GEN_UUID() with argument (value = 7); + * orderliness of generated UUID values according to requirements of v7. + + UUID v7 values have prefix (first 13 bytes) which monotonically grows. + If we generate some number of such UUIDs and write them into the table with integer PK + then this PK and value of row_number()over(order by left(uuid_v7,13)) must be EQUAL + for all records. + Otherwise generated UUID does not match to v7 requirement. +NOTES: + [10.07.2024] pzotov + Checked on 6.0.0.386 +""" + +import pytest +from firebird.qa import * + +init_script = f""" + recreate table test ( + id int generated by default as identity constraint pk_test primary key + ,uuid_v7 varchar(36) unique + ); + + recreate view v_check as + with + a as ( + select id, row_number()over(order by left(uuid_v7,13)) rn, uuid_v7 from test + ) + select * from a where id <> rn + ; + + insert into test(uuid_v7) select uuid_to_char(gen_uuid(7)) from rdb$types rows 50; + commit; +""" + +db = db_factory(init=init_script) +act = python_act('db') + +expected_stdout = f""" +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + with act.db.connect() as con: + cur = con.cursor() + cur.execute('select 1 from v_check') + violates_v7 = cur.fetchone() + if violates_v7: + print('SOME UUIDs DO NOT MEET UUID v7 REQUIREMENTS:') + cur.execute('select id, uuid_v7 from v_check') + act.print_data(cur) + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out # must be EMPTY! + assert act.clean_stdout == act.clean_expected_stdout From 55556e15957ee1bba54e557ae35792b2db060641 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 11 Jul 2024 00:06:56 +0300 Subject: [PATCH 0068/1064] Added/Updated tests\bugs\gh_8176_test.py: Checked on 6.0.0.392-3fa8e6b, 5.0.1.1434-2593b3b. WARNING: SEE NOTES INSIDE. --- tests/bugs/gh_8176_test.py | 194 +++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 tests/bugs/gh_8176_test.py diff --git a/tests/bugs/gh_8176_test.py b/tests/bugs/gh_8176_test.py new file mode 100644 index 00000000..c3abede1 --- /dev/null +++ b/tests/bugs/gh_8176_test.py @@ -0,0 +1,194 @@ +#coding:utf-8 + +""" +ID: issue-8176 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8176 +TITLE: Firebird hangs after starting remote profiling session +DESCRIPTION: + We create two users: tmp_worker_usr and tmp_profiler_usr. + First of them will perform some 'useful work', second will PROFILE attachment of tmp_worker_usr. + Also, we create role 'tmp_profiler_role' and grant it to 'tmp_profiler_usr'. + Ability to profile ather attachment (by tmp_profiler_usr) is achieved via granting to role + tmp_profiler_role system privilege PROFILE_ANY_ATTACHMENT. + Then we create three connections to test DB belonging to tmp_worker_usr, tmp_profiler_usr and SYSDBA. + We pass attachment_id of tmp_worker_usr to the call 'select rdb$profiler.start_session(...)' performed + by tmp_profiler_usr. Executing of this causes creation of PLG$PROFILE* tables and views in the test DB + (they are created by special internal connection - this can be seen in the trace). + Unfortunately, usedr who calls rdb$profiler.start_session() will *NOT* have any access rights to created + PLG* objects. This must be donw explicitly to SYSDBA (and this is the reason why we create 3rd connection). + Finally, we do somewhat similar to example described doc/sql.extensions/README.profiler.md: run two dummy + procedures by tmp_worker_usr, and after that - call proc rdb$profiler.finish_session by tmp_profiler_usr. + At the last step, we query data from plg$prof_sessions (it must have number of records equal to the number + of profiling sessions that we have created). +NOTES: + [10.07.2024] pzotov + ::: WARNING ::: + 1. On CLASSIC problem still exists: firebird hangs, although new connections to test DB are allowed (found both on 5.x and 6.x). + One may even to run 'delete from mon$attachments' (using new ISQL session) but there is no effect: server does not perform that. + Because of this, test currently can be run only on Super. + 2. It looks weird that user (NON-sysdba) who has necessary rights to start profiling, must be explicitly granted to access PLG* tables/views. + + Confirmed bug on 6.0.0.389-cc71c6f (SS), 5.0.1.1432-9d5a60a (SS) - server hanged and did not allow to make new connections to test DB. + Checked on 6.0.0.392-3fa8e6b, 5.0.1.1434-2593b3b. +""" + +import pytest +from firebird.qa import * +from firebird.driver import tpb, Isolation # , TraLockResolution, TraAccessMode, DatabaseError +import time + +N_COUNT = 1000 +init_script = f""" + create or alter procedure sp_ins as begin end; + create or alter procedure sp_del as begin end; + + recreate table test ( + id integer primary key, + val integer not null + ); + + set term ^; + + create or alter function fn_mult(p1 integer, p2 integer) returns integer + as + begin + return p1 * p2; + end^ + + create or alter procedure sp_ins sql security definer + as + declare i integer = 1; + begin + while (i <= {N_COUNT}) + do + begin + if (mod(i, 2) = 1) then + insert into test values (:i, fn_mult(:i, 2)); + i = i + 1; + end + end + ^ + + create or alter procedure sp_del sql security definer + as + declare i integer = 1; + begin + while (i <= {N_COUNT} / 2) + do + begin + if (mod(i, 2) = 1) then + delete from test where id = fn_mult(:i, 2); + i = i + 1; + end + end + ^ + set term ;^ + commit; + + grant execute on procedure sp_ins to public; + grant execute on procedure sp_del to public; + commit; +""" + +tmp_worker_usr = user_factory('db', name='tmp_worker_8176', password='123') +tmp_profiler_usr = user_factory('db', name='tmp_profiler_8176', password='456') +tmp_profiler_role = role_factory('db', name='tmp_profiler_role') + +db = db_factory(init=init_script) +act = python_act('db') + +@pytest.mark.disabled_in_forks +@pytest.mark.version('>=5.0.1') +def test_1(act: Action, tmp_worker_usr: User, tmp_profiler_usr: User, tmp_profiler_role: Role, capsys): + + if act.vars['server-arch'] != 'SuperServer': + pytest.skip("SEE NOTES: currently Super only.") + + addi_script = f""" + set wng off; + set bail on; + alter user {tmp_profiler_usr.name} revoke admin role; + revoke all on all from {tmp_profiler_usr.name}; + commit; + -- doc/sql.extensions/README.profiler.md: + -- If the remote attachment is from a different user, the calling user must have the system privilege `PROFILE_ANY_ATTACHMENT`. + alter role {tmp_profiler_role.name} + set system privileges to PROFILE_ANY_ATTACHMENT; + commit; + grant default {tmp_profiler_role.name} to user {tmp_profiler_usr.name}; + commit; + """ + act.isql(switches=['-q'], input=addi_script) + + custom_tpb = tpb(isolation = Isolation.READ_COMMITTED_READ_CONSISTENCY, lock_timeout = 0) + + with act.db.connect() as con_admin, \ + act.db.connect(user = tmp_worker_usr.name, password = tmp_worker_usr.password) as con_worker, \ + act.db.connect(user = tmp_profiler_usr.name, password = tmp_profiler_usr.password, role = tmp_profiler_role.name) as con_profiler: + + cur_worker = con_worker.cursor() + cur_worker.execute('select current_connection from rdb$database') + worker_attach_id = cur_worker.fetchone()[0] + + tx_profiler = con_profiler.transaction_manager(custom_tpb) + cur_profiler = tx_profiler.cursor() + + #.............................................................................. + + tx_profiler.begin() + cur_profiler.execute(f"select rdb$profiler.start_session('remote_profiling_of_inserts', null, {worker_attach_id}) from rdb$database;") + cur_profiler.fetchall() + + cur_worker.callproc('sp_ins') + + cur_profiler.callproc(f'rdb$profiler.finish_session(true, {worker_attach_id})') + tx_profiler.commit() + + #.............................................................................. + + tx_profiler.begin() + cur_profiler.execute(f"select rdb$profiler.start_session('remote_profiling_of_deletions', null, {worker_attach_id}) from rdb$database;") + cur_profiler.fetchall() + + cur_worker.callproc('sp_del') + + cur_profiler.callproc(f'rdb$profiler.finish_session(true, {worker_attach_id})') + tx_profiler.commit() + + #------------------------------------------------------------------------------ + # firebird.driver.types.DatabaseError: no permission for SELECT access to TABLE PLG$PROF_SESSIONS + # -Effective user is TMP_USER_PROFILER_ANY_ATT + ################################# + # ::: NB ::: Why this is needed ? + ################################# + con_admin.execute_immediate(f'grant select on plg$prof_sessions to role {tmp_profiler_role.name}') + con_admin.execute_immediate(f'grant select on plg$prof_psql_stats_view to role {tmp_profiler_role.name}') + con_admin.commit() + #------------------------------------------------------------------------------ + + tx_profiler.begin() + cur_profiler.execute('select description as profiler_session_descr, attachment_id as profiled_attachment, trim(user_name) as who_was_profiled from plg$prof_sessions order by profile_id') + cur_cols = cur_profiler.description + for r in cur_profiler: + for i in range(0,len(cur_cols)): + print( cur_cols[i][0], ':', r[i] ) + + #cur_profiler.execute('select * from plg$prof_psql_stats_view') + #cur_cols = cur_profiler.description + #for r in cur_profiler: + # for i in range(0,len(cur_cols)): + # print( cur_cols[i][0], ':', r[i] ) + + tx_profiler.commit() + + act.expected_stdout = f""" + PROFILER_SESSION_DESCR : remote_profiling_of_inserts + PROFILED_ATTACHMENT : {worker_attach_id} + WHO_WAS_PROFILED : {tmp_worker_usr.name.upper()} + + PROFILER_SESSION_DESCR : remote_profiling_of_deletions + PROFILED_ATTACHMENT : {worker_attach_id} + WHO_WAS_PROFILED : {tmp_worker_usr.name.upper()} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 01cf8c917ffd40d0a759269b5bcf6dbe33b51a9a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 11 Jul 2024 08:46:41 +0300 Subject: [PATCH 0069/1064] Added/Updated tests\bugs\gh_8178_test.py: Checked on 6.0.0.392, 5.0.1.1434, 4.0.5.3127, 3.0.12.33765 --- tests/bugs/gh_8178_test.py | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/bugs/gh_8178_test.py diff --git a/tests/bugs/gh_8178_test.py b/tests/bugs/gh_8178_test.py new file mode 100644 index 00000000..763d674a --- /dev/null +++ b/tests/bugs/gh_8178_test.py @@ -0,0 +1,77 @@ +#coding:utf-8 + +""" +ID: issue-8178 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8178 +TITLE: Problem with boolean conversion to string inside DataTypeUtil::makeFromList() +DESCRIPTION: +NOTES: + [11.07.2024] pzotov + Confirmed problem on 6.0.0.389. + Checked on 6.0.0.392, 5.0.1.1434, 4.0.5.3127, 3.0.12.33765 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set heading off; + -- set echo on; + select coalesce(1, 'c1') from rdb$database; + + select coalesce('c2', 2) from rdb$database; + + select coalesce('c3', true) from rdb$database; + + select coalesce(true, 'c4') from rdb$database; + + select coalesce(5, true) from rdb$database; + + select coalesce(true, 6) from rdb$database; + + ---------------------------------------------------- + + select coalesce('c7', true, 7) from rdb$database; + + select coalesce('c8', 8, true) from rdb$database; + + select coalesce(true, 'c9', 9) from rdb$database; + + select coalesce(true, 10, 'c10') from rdb$database; + + select coalesce(11, 'c11', true) from rdb$database; + + select coalesce(12, true, 'c12') from rdb$database; +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + 1 + c2 + c3 + TRUE + + Statement failed, SQLSTATE = HY004 + SQL error code = -104 + -Datatypes are not comparable in expression COALESCE + + Statement failed, SQLSTATE = HY004 + SQL error code = -104 + -Datatypes are not comparable in expression COALESCE + + c7 + c8 + TRUE + TRUE + 11 + 12 +""" + +@pytest.mark.version('>=3.0.12') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 34f48ef94505a35a22afbf7c1ae49b173711d129 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 12 Jul 2024 10:08:47 +0300 Subject: [PATCH 0070/1064] Added/Updated tests\functional\replication\test_blob_access_when_no_grant_for_select.py: Checked on 6.0.0.395 (SS/CS), 5.0.1.1439, 4.0.5.3127 --- ...st_blob_access_when_no_grant_for_select.py | 479 ++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 tests/functional/replication/test_blob_access_when_no_grant_for_select.py diff --git a/tests/functional/replication/test_blob_access_when_no_grant_for_select.py b/tests/functional/replication/test_blob_access_when_no_grant_for_select.py new file mode 100644 index 00000000..80422e6e --- /dev/null +++ b/tests/functional/replication/test_blob_access_when_no_grant_for_select.py @@ -0,0 +1,479 @@ +#coding:utf-8 + +""" +ID: replication.test_blob_access_when_no_grant_for_select +ISSUE: None. +TITLE: Replicator must have access to the table with blob regardless SELECT grant on this table to the user who created blob. +DESCRIPTION: + We create table and user ('tmp_nonpriv_user'), with revoking all grants from him except only one: allow INSERT to that table (w/o select!). + The last DDL that we do is creating table with name 't_completed'. It serves as 'flag' to be checked that all DDL actions + on master finished. + + After this we wait until replica becomes actual to master, and this delay will last no more then threshold that + is defined by MAX_TIME_FOR_WAIT_DATA_IN_REPLICA variable (measured in seconds), see QA_ROOT/files/test_config.ini + + Then we connect to master as and run DML against table 'test': insert one record. + Normally it must NOT raise any error (see 'dml_err') on master, but before fix replicator thread failed at this point with access problems + to blob data and replication.log was filled with messages: + ERROR: no permission for SELECT access to ... + Effective user is + ERROR: Replication is stopped due to critical error(s) + + We must check here that replica DB eventually will have appropriate blob in the test table (see 'isql_expected_out'). + NOTE. We have to avoid query of replication log - not only verbose can be disabled, but also because code is too complex. + + Further, we invoke ISQL with executing auxiliary script for drop all DB objects on master (with '-nod' command switch). + After all objects will be dropped, we have to wait again until replica becomes actual with master. + Check that both DB have no custom objects is performed (see UNION-ed query to rdb$ tables + filtering on rdb$system_flag). + + Finally, we extract metadata for master and replica and make comparison. + The only difference in metadata must be 'CREATE DATABASE' statement with different DB names - we suppress it, + thus metadata difference must not be issued. + +NOTES: + There is no ticket for this test. + Frontported fix was 30.06.2024: + * for 5.x: https://github.com/FirebirdSQL/firebird/commit/97358d012c798aa4382c863404f3dd22befe1af6 + * for 6.x: https://github.com/FirebirdSQL/firebird/commit/caf7a6bcf8dd13790c4c0ffa52ff1bec9e46f07f + Log message: Frontported bugfix for blob access vs replicator + + We use 'assert' only at the final point of test, with printing detalization about encountered problem(s). + During all previous steps, we only store unexpected output to variables, e.g.: out_main = capsys.readouterr().out etc. + + Confirmed bug on 6.0.0.387, 5.0.1.1428. + Checked on 6.0.0.395 (SS/CS), 5.0.1.1439, 4.0.5.3127 + + Thanks to dimitr for suggestions. +""" +import os +import shutil +from difflib import unified_diff +from pathlib import Path +import time + +import pytest +from firebird.qa import * +from firebird.driver import connect, create_database, DbWriteMode, ReplicaMode, ShutdownMode, ShutdownMethod, DatabaseError + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +repl_settings = QA_GLOBALS['replication'] + +MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) +MAIN_DB_ALIAS = repl_settings['main_db_alias'] +REPL_DB_ALIAS = repl_settings['repl_db_alias'] +RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) + +db_main = db_factory( filename = '#' + MAIN_DB_ALIAS, do_not_create = True, do_not_drop = True) +db_repl = db_factory( filename = '#' + REPL_DB_ALIAS, do_not_create = True, do_not_drop = True) + +tmp_nonpriv_user = user_factory('db_main', name='tmp_replicator_blob_access', password='123') + +substitutions = [('Start removing objects in:.*', 'Start removing objects'), + ('Finish. Total objects removed: [1-9]\\d*', 'Finish. Total objects removed'), + ('.* CREATE DATABASE .*', ''), + ('[\t ]+', ' '), + ('FOUND message about replicated segment N .*', 'FOUND message about replicated segment')] + +act_db_main = python_act('db_main', substitutions=substitutions) +act_db_repl = python_act('db_repl', substitutions=substitutions) + +#-------------------------------------------- + +def cleanup_folder(p): + # Removed all files and subdirs in the folder

+ # Used for cleanup and when replication must be reset + # in case when any error occurred during test execution. + assert os.path.dirname(p) != p, f"@@@ ABEND @@@ CAN NOT operate in the file system root directory. Check your code!" + + for root, dirs, files in os.walk(p): + for f in files: + # ::: NB ::: 22.12.2023. + # We have to expect that attempt to delete of GUID and (maybe) archived segments can FAIL with + # PermissionError: [WinError 32] The process cannot ... used by another process: /path/to/{GUID} + # Also, we have to skip exception if file (segment) was just deleted by engine + try: + Path(root +'/' + f).unlink(missing_ok = True) + except PermissionError as x: + pass + + for d in dirs: + shutil.rmtree(os.path.join(root, d), ignore_errors = True) + + return os.listdir(p) + +#-------------------------------------------- + +def reset_replication(act_db_main, act_db_repl, db_main_file, db_repl_file): + out_reset = '' + failed_shutdown_db_map = {} # K = 'db_main', 'db_repl'; V = error that occurred when we attempted to change DB state to full shutdown (if it occurred) + + with act_db_main.connect_server() as srv: + + # !! IT IS ASSUMED THAT REPLICATION FOLDERS ARE IN THE SAME DIR AS !! + # DO NOT use 'a.db.db_path' for ALIASED database! + # It will return '.' rather than full path+filename. + + repl_root_path = Path(db_main_file).parent + repl_jrn_sub_dir = repl_settings['journal_sub_dir'] + repl_arc_sub_dir = repl_settings['archive_sub_dir'] + + for f in (db_main_file, db_repl_file): + # Method db.drop() changes LINGER to 0, issues 'delete from mon$att' with suppressing exceptions + # and calls 'db.drop_database()' (also with suppressing exceptions). + # We change DB state to FULL SHUTDOWN instead of call action.db.drop() because + # this is more reliable (it kills all attachments in all known cases and does not use mon$ table) + # + try: + srv.database.shutdown(database = f, mode = ShutdownMode.FULL, method = ShutdownMethod.FORCED, timeout = 0) + + # REMOVE db file from disk: we can safely assume that this can be done because DB in full shutdown state. + ########################### + os.unlink(f) + except DatabaseError as e: + failed_shutdown_db_map[ f ] = e.__str__() + + + # Clean folders repl_journal and repl_archive: remove all files from there. + # NOTE: test must NOT raise unrecoverable error if some of files in these folders can not be deleted. + # Rather, this must be displayed as diff and test must be considered as just failed. + for p in (repl_jrn_sub_dir,repl_arc_sub_dir): + + remained_files = cleanup_folder(repl_root_path/p) + + if remained_files: + out_reset += '\n'.join( (f"Directory '{str(repl_root_path/p)}' remains non-empty. Could not delete file(s):", '\n'.join(remained_files)) ) + + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxx r e c r e a t e d b _ m a i n a n d d b _ r e p l xxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + for a in (act_db_main,act_db_repl): + d = a.db.db_path + failed_shutdown_msg = failed_shutdown_db_map.get( str(d), '' ) + if failed_shutdown_msg: + # we could NOT change state of this database to full shutdown --> we must NOT recreate it. + # Accumulate error messages in OUT arg (for displaying as diff): + # + out_reset += '\n'.join( failed_shutdown_msg ) + else: + try: + dbx = create_database(str(d), user = a.db.user) + dbx.close() + with a.connect_server() as srv: + srv.database.set_write_mode(database = d, mode = DbWriteMode.ASYNC) + srv.database.set_sweep_interval(database = d, interval = 0) + if a == act_db_repl: + srv.database.set_replica_mode(database = d, mode = ReplicaMode.READ_ONLY) + else: + with a.db.connect() as con: + con.execute_immediate('alter database enable publication') + con.execute_immediate('alter database include all to publication') + con.commit() + except DatabaseError as e: + out_reset += e.__str__() + + # Must remain EMPTY: + #################### + return out_reset + +#-------------------------------------------- + +def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + + retcode = 1; + ready_to_check = False + if ddl_ready_query: + with a.db.connect(no_db_triggers = True) as con: + with con.cursor() as cur: + for i in range(0,max_allowed_time_for_wait): + cur.execute(ddl_ready_query) + count_actual = cur.fetchone() + if count_actual: + ready_to_check = True + break + else: + con.rollback() + time.sleep(1) + else: + ready_to_check = True + + if not ready_to_check: + print( f'UNEXPECTED. Initial check query did not return any rows for {max_allowed_time_for_wait} seconds.' ) + print('Initial check query:') + print(ddl_ready_query) + return + + final_check_pass = False + if isql_check_script: + retcode = 0 + for i in range(max_allowed_time_for_wait): + a.reset() + a.expected_stdout = replica_expected_out + a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) + + if a.return_code: + # "Token unknown", "Name longer than database column size" etc: we have to + # immediately break from this loop because isql_check_script is incorrect! + break + + if a.clean_stdout == a.clean_expected_stdout: + final_check_pass = True + break + if i < max_allowed_time_for_wait-1: + time.sleep(1) + + if not final_check_pass: + print(f'UNEXPECTED. Final check query did not return expected dataset for {max_allowed_time_for_wait} seconds.') + print('Final check query:') + print(isql_check_script) + print('Expected output:') + print(a.clean_expected_stdout) + print('Actual output:') + print(a.clean_stdout) + print(f'ISQL return_code={a.return_code}') + print(f'Waited for {i} seconds') + + a.reset() + + else: + final_check_pass = True + + return + +#-------------------------------------------- + +def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): + + # return initial state of master DB: + # remove all DB objects (tables, views, ...): + # + db_main_meta, db_repl_meta = '', '' + for a in (act_db_main,act_db_repl): + if a == act_db_main: + sql_clean = (a.files_dir / 'drop-all-db-objects.sql').read_text() + a.expected_stdout = """ + Start removing objects + Finish. Total objects removed + """ + a.isql(switches=['-q', '-nod'], input = sql_clean, combine_output = True) + + if a.clean_stdout == a.clean_expected_stdout: + a.reset() + else: + print(a.clean_expected_stdout) + a.reset() + break + + # NB: one need to remember that rdb$system_flag can be NOT ONLY 1 for system used objects! + # For example, it has value =3 for triggers that are created to provide CHECK-constraints, + # Custom DB objects always have rdb$system_flag = 0 (or null for some very old databases). + # We can be sure that there are no custom DB objects if following query result is NON empty: + # + ddl_ready_query = """ + select 1 + from rdb$database + where NOT exists ( + select custom_db_object_flag + from ( + select rt.rdb$system_flag as custom_db_object_flag from rdb$triggers rt + UNION ALL + select rt.rdb$system_flag from rdb$relations rt + UNION ALL + select rt.rdb$system_flag from rdb$functions rt + UNION ALL + select rt.rdb$system_flag from rdb$procedures rt + UNION ALL + select rt.rdb$system_flag from rdb$exceptions rt + UNION ALL + select rt.rdb$system_flag from rdb$fields rt + UNION ALL + select rt.rdb$system_flag from rdb$collations rt + UNION ALL + select rt.rdb$system_flag from rdb$generators rt + UNION ALL + select rt.rdb$system_flag from rdb$roles rt + UNION ALL + select rt.rdb$system_flag from rdb$auth_mapping rt + UNION ALL + select 1 from sec$users s + where upper(s.sec$user_name) <> 'SYSDBA' + ) t + where coalesce(t.custom_db_object_flag,0) = 0 + ) + """ + + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + print(capsys.readouterr().out) + + db_main_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + else: + db_repl_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + + if RUN_SWEEP_AT_END: + # Following sweep was mandatory during 2021...2022. Problem was fixed: + # * for FB 4.x: 26-jan-2023, commit 2ed48a62c60c029cd8cb2b0c914f23e1cb56580a + # * for FB 5.x: 20-apr-2023, commit 5af209a952bd2ec3723d2c788f2defa6b740ff69 + # (log message: 'Avoid random generation of field IDs, respect the user-specified order instead'). + # Until this problem was solved, subsequent runs of this test caused to fail with: + # 'ERROR: Record format with length NN is not found for table TEST' + # + a.gfix(switches=['-sweep', a.db.dsn]) + + # Final point: metadata must become equal: + # + diff_meta = ''.join(unified_diff( \ + [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], + [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) + ) + # Must be EMPTY: + print(diff_meta) + +#-------------------------------------------- + +@pytest.mark.replication +@pytest.mark.version('>=4.0.5') +def test_1(act_db_main: Action, act_db_repl: Action, tmp_nonpriv_user: User, capsys): + + out_prep, out_main, out_drop, dml_err = '', '', '', '' + # Obtain full path + filename for DB_MAIN and DB_REPL aliases. + # NOTE: we must NOT use 'a.db.db_path' for ALIASED databases! + # It will return '.' rather than full path+filename. + # Use only con.info.name for that! + # + db_info = {} + for a in (act_db_main, act_db_repl): + with a.db.connect() as con: + db_info[a, 'db_full_path'] = con.info.name + + # Must be EMPTY: + out_prep = capsys.readouterr().out + if out_prep: + # Some problem raised during change DB header(s) + pass + else: + sql_init = f""" + set bail on; + set wng off; + recreate table test ( + id int generated by default as identity constraint test_pk primary key + ,who varchar(31) default current_user + ,dts timestamp default 'now' + -- NB: we have to specify 'sub_tupe' here, otherwise attempt to insert data in this blob will fail with + -- "TypeError: String value is not acceptable type for a non-textual BLOB column." + -- (in cur.execute() with parametrized expr, see below). + -- It looks strange but this error does NOT appear in case if we use con.execute_immediate(). + ,bdata blob sub_type 1 + ); + commit; + recreate view v_test as select id, who, bdata from test; + revoke all on all from {tmp_nonpriv_user.name}; + grant insert on v_test to {tmp_nonpriv_user.name}; + commit; + + recreate table t_completed(id int primary key); + commit; + """ + act_db_main.isql(switches=['-q'], input = sql_init, combine_output = True) + out_prep = act_db_main.clean_stdout + act_db_main.reset() + + if out_prep: + # Some problem raised during init_sql execution + pass + else: + # Query to be used for check that all DB objects present in replica (after last DML statement completed on master DB): + ddl_ready_query = "select 1 from rdb$relations where rdb$relation_name = upper('t_completed')" + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + # Must be EMPTY: + out_prep = capsys.readouterr().out + + test_blob_data = 'test blob data' + + if out_prep: + # Some problem raised with delivering DDL changes to replica + pass + else: + + with act_db_main.db.connect(user = tmp_nonpriv_user.name, password = tmp_nonpriv_user.password) as con: # , charset = 'utf-8') as con: + cur = con.cursor() + try: + # ERROR: no permission for SELECT access to ... + # Effective user is ... + # ERROR: Replication is stopped due to critical error(s) + # + cur.execute("insert into v_test(bdata) values(?)", (test_blob_data,)) + con.commit() + except DatabaseError as e: + dml_err = e.__str__() + + if dml_err: + # Some problem raised with writing blob into master DB + pass + else: + # No errors must be now. We have to wait now until blob from MASTER be delivered to REPLICA. + # Query to be used that replica DB contains all expected data (after last DML statement completed on master DB): + isql_check_script = """ + set bail on; + set list on; + set count on; + select + rdb$get_context('SYSTEM','REPLICA_MODE') replica_mode + ,who + ,cast(bdata as varchar(32760)) as bdata + from v_test; + """ + + isql_expected_out = f""" + REPLICA_MODE READ-ONLY + WHO {tmp_nonpriv_user.name.upper()} + BDATA {test_blob_data} + Records affected: 1 + """ + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, '', isql_check_script, isql_expected_out) + # Must be EMPTY: + out_main = capsys.readouterr().out + + drop_db_objects(act_db_main, act_db_repl, capsys) + + # Must be EMPTY: + out_drop = capsys.readouterr().out + + if [ x for x in (out_prep, out_main, dml_err, out_drop) if x.strip() ]: + # We have a problem either with DDL/DML or with dropping DB objects. + # First, we have to RECREATE both master and slave databases + # (otherwise further execution of this test or other replication-related tests most likely will fail): + out_reset = reset_replication(act_db_main, act_db_repl, db_info[act_db_main,'db_full_path'], db_info[act_db_repl,'db_full_path']) + + # Next, we display out_main, out_drop and out_reset: + # + print('Problem(s) detected:') + if out_prep.strip(): + print('out_prep:') + print(out_prep) + if out_main.strip(): + print('out_main:') + print(out_main) + if dml_err.strip(): + print('dml_err:') + print(dml_err) + if out_drop.strip(): + print('out_drop:') + print(out_drop) + if out_reset.strip(): + print('out_reset:') + print(out_reset) + + assert '' == capsys.readouterr().out From 0c377bc87f82dde02c7a8461eecd8af1aa077d7c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 12 Jul 2024 13:11:40 +0300 Subject: [PATCH 0071/1064] Added/Updated tests\bugs\gh_8178_addi_test.py: Checked on 6.0.0.392, 5.0.1.1434, 4.0.5.3127, 3.0.12.33765 --- tests/bugs/gh_8178_addi_test.py | 117 ++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/bugs/gh_8178_addi_test.py diff --git a/tests/bugs/gh_8178_addi_test.py b/tests/bugs/gh_8178_addi_test.py new file mode 100644 index 00000000..cbceb042 --- /dev/null +++ b/tests/bugs/gh_8178_addi_test.py @@ -0,0 +1,117 @@ +#coding:utf-8 + +""" +ID: issue-8178 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8178 +TITLE: Check result of conversion to string in COALESCE that involves all families of data types. +DESCRIPTION: + Additional test for gh_8178 +NOTES: + [12.07.2024] pzotov + Checked on 6.0.0.392, 5.0.1.1434, 4.0.5.3127, 3.0.12.33765 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table dvalues( + t_int int default 12345 + ,t_boo boolean default true + ,t_chr char default 'A' + ,t_blb blob default 'bbbbbbblllllllloooooooooobbbbbbbb' + ,t_dat date default '01.01.1991' + ,t_tim time default '01:02:03.456' + ,t_tst timestamp default '01.02.2003 23:34:56' + ,t_nul char default null + ); + insert into dvalues default values; + commit; + --------------------------------------------------------- + recreate table dtypes(f smallint, t varchar(20)); + insert into dtypes(f,t) values( 1,'int'); + insert into dtypes(f,t) values( 2,'boo'); + insert into dtypes(f,t) values( 3,'chr'); + insert into dtypes(f,t) values( 4,'blb'); + insert into dtypes(f,t) values( 5,'dat'); + insert into dtypes(f,t) values( 6,'tim'); + insert into dtypes(f,t) values( 7,'tst'); + --insert into dtypes(f,t) values( 8,'nul'); + commit; + + set count on; + + set term ^; + execute block returns( checked_expr varchar(1024), raised_gds int) as + declare v_expr varchar(1024); + declare v_done smallint; + begin + for + select + --a.t as a_t, b.t as b_t, c.t as c_t, d.t as d_t, e.t as e_t, f.t as f_t, g.t as g_t + --,a.f as a_f, b.f as b_f, c.f as c_f, d.f as d_f, e.f as e_f, f.f as f_f, g.f as g_f, + 'select iif( coalesce(' + || + iif( a.t = 'nul', 'null', 't_'||a.t) + || + iif( b.t = 'nul', ', null', ', t_'||b.t) + || + iif( c.t = 'nul', ', null', ', t_'||c.t) + || + iif( d.t = 'nul', ', null', ', t_'||d.t) + || + iif( e.t = 'nul', ', null', ', t_'||e.t) + || + iif( f.t = 'nul', ', null', ', t_'||f.t) + || + iif( g.t = 'nul', ', null', ', t_'||g.t) + || + ') is distinct from null, 1, 0 ) as x from dvalues' as expr + from dtypes a + cross join dtypes b + cross join dtypes c + cross join dtypes d + cross join dtypes e + cross join dtypes f + cross join dtypes g + where + a.f not in (b.f, c.f, d.f, e.f, f.f, g.f) + and b.f not in (c.f, d.f, e.f, f.f, g.f) + and c.f not in (d.f, e.f, f.f, g.f) + and d.f not in (e.f, f.f, g.f) + and e.f not in (f.f, g.f) + and f.f not in (g.f) + order by a.t, b.t, c.t, d.t, e.t, f.t, g.t + as cursor k + do begin + checked_expr = k.expr; + raised_gds = 0; + begin + execute statement checked_expr into v_done; + when any do + begin + raised_gds = gdscode; + end + end + if (raised_gds <> 0) then + suspend; + end + end + ^ + set term ;^ +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + Records affected: 0 +""" + +@pytest.mark.version('>=3.0.12') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0ed0e705e605767f2c4e8936ddf5bc8c4aa64a58 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 14 Jul 2024 11:47:45 +0300 Subject: [PATCH 0072/1064] Added/Updated tests\functional\tabloid\test_crash_when_too_long_username_for_auth.py: Customized for run against dev build after Dimitry Sibiryakov request: filter out second item from dev status vector: 335544882 / Login name too long --- ...t_crash_when_too_long_username_for_auth.py | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/functional/tabloid/test_crash_when_too_long_username_for_auth.py b/tests/functional/tabloid/test_crash_when_too_long_username_for_auth.py index a57ac711..5d17cc41 100644 --- a/tests/functional/tabloid/test_crash_when_too_long_username_for_auth.py +++ b/tests/functional/tabloid/test_crash_when_too_long_username_for_auth.py @@ -4,10 +4,19 @@ TITLE: crash on assert or memory corruption when too long username is used for authentication NOTES: [19.07.2023] pzotov - Confirmed problem on 3.x only (3.0.11.33690). + Confirmed problem on 3.x only (3.0.11.33690): server crashed, client got: + Statement failed, SQLSTATE = 08004 + connection rejected by remote interface FB 4.0.3.2956 and 5.0.0.1093 (builds before 29-JUN-2023) issued "SQLSTATE = 28000 / Your user name and password..." but not crashed. After fix, all three FB issue "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log for details" Checked on 3.0.11.33965 -- all OK. + + [14.07.2024] pzotov + Customized for run against dev build after Dimitry Sibiryakov request. + Dev build issues status vector containing TWO elements: + 335545106 ==> Error occurred during login, please check server firebird.log for details + 335544882 ==> Login name too long (@1 characters, maximum allowed @2) + We can filter out its second item.. """ import locale import re @@ -15,26 +24,32 @@ import pytest from firebird.qa import * +from firebird.driver import DatabaseError -db = db_factory() # charset = 'utf8', init = init_sql) +db = db_factory() -act = python_act( 'db', substitutions=[('[ \t]+',' ')] ) +act = python_act( 'db', substitutions=[('[ \t]+',' '), ('.*Login name too long.*', '')] ) @pytest.mark.version('>=3.0.11') def test_1(act: Action, capsys): - MAX_NAME_LEN = 31 if act.is_version('<=3') else 63 - TOO_LONG_USR = 'u1111111111222222222233333333334444444444555555555566666666667777777777' - test_sql = f""" - connect '{act.db.dsn}' user '{TOO_LONG_USR}' password 'qqq'; - quit; - """ - - expected_stdout = """ - Statement failed, SQLSTATE = 08006 + TOO_LONG_USR = 'u2345678901234567890123456789012345678901234567890123456789012345678901' + # 1 2 3 4 5 6 7 + try: + with act.db.connect(user = TOO_LONG_USR, password = 'qwe', charset = 'win1251'): + pass + except DatabaseError as e: + # ACHTUNG: dev-build will raise error with TWO gdscodes: [335545106, 335544882]. + # 335545106 ==> Error occurred during login, please check server firebird.log for details + # 335544882 ==> Login name too long (@1 characters, maximum allowed @2) + # We have to check only first of them. DO NOT iterate through gds_codes tuple! + print( e.gds_codes[0] ) + print( e.__str__() ) + + act.stdout = capsys.readouterr().out + act.expected_stdout = """ + 335545106 Error occurred during login, please check server firebird.log for details """ - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], charset = 'win1251', credentials = False, connect_db = False, input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From 78ef0af3a501777fd2ae5c211d0965078b120e9b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 16 Jul 2024 13:33:39 +0300 Subject: [PATCH 0073/1064] Added/Updated tests\bugs\gh_7652_test.py: Checked on 6.0.0.395 --- tests/bugs/gh_7652_test.py | 130 +++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 tests/bugs/gh_7652_test.py diff --git a/tests/bugs/gh_7652_test.py b/tests/bugs/gh_7652_test.py new file mode 100644 index 00000000..973e665f --- /dev/null +++ b/tests/bugs/gh_7652_test.py @@ -0,0 +1,130 @@ +#coding:utf-8 + +""" +ID: issue-7652 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7652 +TITLE: Make the profiler store aggregated requests by default, with option for detailed store +DESCRIPTION: + Test executes two times script with loop which does call to trivial stored procedure. + First time we launch profiler without any parameters except session name, then - with 'DETAILED_REQUESTS'. + In both cases (after finish profiling) we run SQL against tables plg$prof_requests and plg$prof_psql_stats + and obtain TWO aggregated values: count number of records with request_id = 0 and request_id <> 0. + For case when we call profiler WITHOUT any parameters (except session name): + * before this ticket was implemented (for builds with date <= 27-JUN-2023) data in both mentioned tables + did not contain records with request_id = 0 (i.e. all rows had request_id > 0); + * after implementation ( https://github.com/FirebirdSQL/firebird/commit/00bb8e4581b66b624de47bfcde6b248e163ec6c1 ) + all rows in tables plg$prof_requests and plg$prof_psql_stats have request_id > 0. + For case when we call profiler WITH 'DETAILED_REQUESTS': + * builds with date <= 27-JUN-2023 could not be used, exception raised: + Statement failed, SQLSTATE = 42000 + validation error for variable ATTACHMENT_ID, value "*** null ***" + -At function 'RDB$PROFILER.START_SESSION' + * after implementation all rows in tables plg$prof_requests and plg$prof_psql_stats have request_id > 0. +NOTES: + Compared 5.0.0.1087 (26-JUN-2023) vs 5.0.0.1088 (27-JUN-2023) + Checked on 6.0.0.395 +""" +import pytest +from firebird.qa import * +import locale +import re + +db = db_factory() +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +def strip_white(value): + value = re.sub('(?m)^\\s+', '', value) + return re.sub('(?m)\\s+$', '', value) + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + actual_out = '' + test_sql = f""" + set bail on; + set list on; + set term ^; + create or alter procedure sp_rand_pair(a_i smallint) returns(r double precision, s varchar(36)) as + begin + if ( mod(a_i, 2) = 0 ) then + begin + r = -1; + s = ''; + end + else + begin + r = rand(); + s = uuid_to_char(gen_uuid()); + end + suspend; + end + ^ + set term ;^ + commit; + + --set echo on; + %(debug_message_sttm)s; + %(profiler_start_sttm)s; + --set echo off; + + set term ^; + execute block as + declare i int = 3; + declare r double precision; + declare s varchar(36); + begin + while (i > 0) do + begin + select r,s from sp_rand_pair( :i ) into r,s; + i = i - 1; + end + end + ^ + set term ;^ + execute procedure rdb$profiler.finish_session(true); + commit; + + set transaction read committed; + + select + iif( sum( iif(request_id = 0, 1, 0) ) > 0, 'NON_ZERO', 'ZERO' ) as requests_cnt_zero_request_id + ,iif( sum( iif(request_id = 0, 0, 1) ) > 0, 'NON_ZERO', 'ZERO' ) as requests_cnt_non_zero_req_id + from plg$prof_requests; + + select + iif( sum( iif(request_id = 0, 1, 0) ) > 0, 'NON_ZERO', 'ZERO' ) as psql_stats_cnt_zero_request_id + ,iif( sum( iif(request_id = 0, 0, 1) ) > 0, 'NON_ZERO', 'ZERO' ) as psql_stats_cnt_non_zero_req_id + from plg$prof_psql_stats; + """ + + + debug_message_sttm = "select 'DETAILED_REQUESTS: OFF' as msg from rdb$database" + profiler_start_sttm = "select sign(rdb$profiler.start_session('prof_ssn_no_details')) from rdb$database" + act.isql(input = test_sql % locals(), combine_output = True) + actual_out += act.clean_stdout + '\n' + act.reset() + + #------------------------------------------------------------------------------------------------------- + + debug_message_sttm = "select 'DETAILED_REQUESTS: ON' as msg from rdb$database" + profiler_start_sttm = "select sign(rdb$profiler.start_session('prof_ssn_with_details', null, null, null, 'DETAILED_REQUESTS')) from rdb$database" + act.isql(input = test_sql % locals(), combine_output = True) + actual_out += act.clean_stdout + '\n' + act.reset() + + expected_out = f""" + MSG DETAILED_REQUESTS: OFF + SIGN 1 + REQUESTS_CNT_ZERO_REQUEST_ID NON_ZERO + REQUESTS_CNT_NON_ZERO_REQ_ID ZERO + PSQL_STATS_CNT_ZERO_REQUEST_ID NON_ZERO + PSQL_STATS_CNT_NON_ZERO_REQ_ID ZERO + + MSG DETAILED_REQUESTS: ON + SIGN 1 + REQUESTS_CNT_ZERO_REQUEST_ID NON_ZERO + REQUESTS_CNT_NON_ZERO_REQ_ID NON_ZERO + PSQL_STATS_CNT_ZERO_REQUEST_ID NON_ZERO + PSQL_STATS_CNT_NON_ZERO_REQ_ID NON_ZERO + """ + assert strip_white(actual_out) == strip_white(expected_out) From 7443cdfd8373940f4f945803cb17b6eada755d51 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 16 Jul 2024 16:32:47 +0300 Subject: [PATCH 0074/1064] Added/Updated tests\bugs\gh_8168_test.py: Checked on 6.0.0.387, 5.0.1.1428. Thanks to Vlad for suggestion about test implementation. --- tests/bugs/gh_8168_test.py | 147 +++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 tests/bugs/gh_8168_test.py diff --git a/tests/bugs/gh_8168_test.py b/tests/bugs/gh_8168_test.py new file mode 100644 index 00000000..605aa073 --- /dev/null +++ b/tests/bugs/gh_8168_test.py @@ -0,0 +1,147 @@ +#coding:utf-8 + +""" +ID: issue-8168 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8168 +TITLE: MAKE_DBKEY bug after backup/restore +DESCRIPTION: + Test creates two tables (tab_1, tab_2) and stores their relation_id in appropriate context variables. + Then we drop these tables and create them again but in 'reverse' order: tab_2, tab_1. + At this point we have to check that values of relation_id must differ for both tables and raise error + (see 'exc_rel_id_not_changed') if this is not so. Test logic must be changed if this error raises. + Then we add one row into each table and create SP (sp_chk) that uses make_dbkey() for returning these + rows. Key note: this SP *must* find appropriate record for each table. + Otherwise (if record not found) we raise exception exc_invalid_make_dbkey. + Finally, we do backup / restore and repeat call of sp_chk. It must return same ID values as before b/r. +NOTES: + [16.07.2024] pzotov + Confirmed bug on 6.0.0.386, 5.0.1.1425. + Checked on 6.0.0.387, 5.0.1.1428. + + Thanks to Vlad for suggestion about test implementation. +""" +import pytest +from firebird.qa import * +from io import BytesIO +from firebird.driver import SrvRestoreFlag +import locale + +db = db_factory() +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0.1') +def test_1(act: Action, capsys): + + init_sql = f""" + set bail on; + set list on; + create exception exc_rel_id_not_changed 'RELATION_ID not changed table(s): @1. One need to change test logic!'; + create exception exc_invalid_make_dbkey 'Invalid make_dbkey() detected for table(s): @1'; + + create view v_get_rel_id as + select + max( iif( upper(rdb$relation_name) = 'TAB_1', rdb$relation_id, null ) ) as t1_rel_id + ,max( iif( upper(rdb$relation_name) = 'TAB_2', rdb$relation_id, null ) ) as t2_rel_id + from rdb$relations + where rdb$relation_name starting with upper('tab_') + ; + create table tab_1(id int); + create table tab_2(id int); + commit; + + set term ^; + execute block as + begin + for + select t1_rel_id, t2_rel_id + from v_get_rel_id + as cursor c + do begin + rdb$set_context('USER_SESSION', 'TAB1_REL_ID', c.t1_rel_id); + rdb$set_context('USER_SESSION', 'TAB2_REL_ID', c.t2_rel_id); + end + end + ^ + set term ;^ + + drop table tab_1; + drop table tab_2; + + recreate table tab_2(id int); + recreate table tab_1(id int); + commit; + + set term ^; + execute block as + declare v_list varchar(100) = ''; + begin + for + select t1_rel_id, t2_rel_id + from v_get_rel_id + as cursor c + do begin + if (c.t1_rel_id = rdb$get_context('USER_SESSION', 'TAB1_REL_ID')) then + v_list = v_list || 'TAB_1; '; + if (c.t2_rel_id = rdb$get_context('USER_SESSION', 'TAB2_REL_ID')) then + v_list = v_list || 'TAB_2'; + + if (v_list > '') then + exception exc_rel_id_not_changed using(v_list); + end + end + ^ + set term ;^ + + ----------------------------------------- + + insert into tab_1(id) values(1); + insert into tab_2(id) values(2); + commit; + + set term ^; + create or alter procedure sp_chk returns (id1 int, id2 int) as + declare v_list varchar(100) = ''; + begin + select id from tab_1 where rdb$db_key = make_dbkey('TAB_1', 0) into id1; + if (row_count = 0) then v_list = v_list || 'TAB_1; '; + + select id from tab_2 where rdb$db_key = make_dbkey('TAB_2', 0) into id2; + if (row_count = 0) then v_list = v_list || 'TAB_2'; + + if (v_list > '') then + exception exc_invalid_make_dbkey using(v_list); + + suspend; + end + ^ + set term ;^ + commit; + select * from sp_chk; + + """ + + expected_stdout = """ + ID1 1 + ID2 2 + """ + act.expected_stdout = expected_stdout + act.isql(input = init_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + #--------------------------------------------------- + + backup = BytesIO() + + with act.connect_server() as srv: + srv.database.local_backup(database=act.db.db_path, backup_stream=backup) + backup.seek(0) + srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags = SrvRestoreFlag.REPLACE) + + act.expected_stdout = """ + ID1 1 + ID2 2 + """ + act.isql(input = "set list on; select * from sp_chk;", combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 70f7a6ac1b63f7718a7e3b81798d71574b26dc6a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 18 Jul 2024 17:16:24 +0300 Subject: [PATCH 0075/1064] Added mark 'scroll_cur' for upcoming tests that deal with scrollable cursor --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index f94fcd5a..90668c59 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,6 +3,7 @@ console_output_style = count # testpaths = tests # addopts = --server local --install-terminal markers = + scroll_cur: mark a test as dealing with scrollable cursor es_eds: mark a test as dealing with ES/EDS mechanism trace: mark a test as dealing with trace encryption: mark a test as dealing with encryption plugin From dc8d2ca264c1e5c58b9b639622c1f43149bbc7a4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 18 Jul 2024 17:16:57 +0300 Subject: [PATCH 0076/1064] Added/Updated tests\bugs\gh_7056_test.py: Checked on 6.0.0.396, 5.0.1.1440. SEE NOTES. --- tests/bugs/gh_7056_test.py | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/bugs/gh_7056_test.py diff --git a/tests/bugs/gh_7056_test.py b/tests/bugs/gh_7056_test.py new file mode 100644 index 00000000..4655a45d --- /dev/null +++ b/tests/bugs/gh_7056_test.py @@ -0,0 +1,52 @@ +#coding:utf-8 + +""" +ID: issue-8168 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8168 +TITLE: Fetching from a scrollable cursor may overwrite user-specified buffer and corrupt memory +DESCRIPTION: Engine did overwrite the user-specified buffer with four more bytes than expected that could corrupt the caller memory. +NOTES: + [18.07.2024] pzotov + 1. Apropriate script without QA plugin caused crash of Python up to 5.0.0.325 (30-nov-2021). + Snapshot 5.0.0.326-fd6bf8d (01-dec-2021 08:44) was fixed but only if we run script not under QA plugin. + 2. Despite that fix (fd6bf8d404068417552f9c8d7ae2e232fa860005, 01-dec-2021 11:45), actually all subsequent + FB snapshots still had a problem until 10-jan-2023: running this test on them caused BUGCHECK + "internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 293)" + 3. Eventually problem was solved 10-JAN-2023: + 5.0.0.890-a6ce0ec -- crash + 5.0.0.890-aa847a7 -- OK + 4. Discussed between dimitr, pcisar and pzotov, see letters of 29-30 NOV 2021, + subj: "firebird-driver & scrollable cursors // misc. tests, requested by dimitr" + 5. Problem appeared only for column with width = 32765 characters, thus DB charset must be single-byte, e.g. win1251 etc. + Otherwise (with default charset = 'utf8') this test will fail with: + "SQLSTATE = 54000 / ... or string truncation / -Implementation limit exceeded" + + Checked on 6.0.0.396, 5.0.1.1440 +""" +import pytest +from firebird.qa import * + +N_WIDTH = 32765 + +init_script = f""" + recreate table ts(id int primary key, s varchar({N_WIDTH})); + insert into ts(id,s) values( 1, lpad('', {N_WIDTH}, 'A') ); + commit; +""" +db = db_factory(init=init_script, charset = 'win1251') +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.scroll_cur +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, capsys): + success_msg = 'COMPLETED.' + with act.db.connect() as con: + cur = con.cursor() + cur.open('select id, s from ts order by id') + cur.fetch_first() + print(success_msg) + + act.expected_stdout = f"{success_msg}" + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From aed482d733884d36cfa1a7cb873c0d7d229a791b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 18 Jul 2024 21:15:10 +0300 Subject: [PATCH 0077/1064] =?UTF-8?q?Added/Updated=20tests\bugs\gh=5F7056?= =?UTF-8?q?=5Ftest.py:=20Re-implemented:=20we=20have=20to=20use=20=D1=81us?= =?UTF-8?q?tom=20driver-config=20object=20must=20be=20used=20for=20DPB=20b?= =?UTF-8?q?ecause=20TWO=20protocols=20are=20checked=20here,=20LOCAL=20and?= =?UTF-8?q?=20REMOTE.=20See=20notes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/bugs/gh_7056_test.py | 82 ++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/tests/bugs/gh_7056_test.py b/tests/bugs/gh_7056_test.py index 4655a45d..157a6f52 100644 --- a/tests/bugs/gh_7056_test.py +++ b/tests/bugs/gh_7056_test.py @@ -4,49 +4,89 @@ ID: issue-8168 ISSUE: https://github.com/FirebirdSQL/firebird/issues/8168 TITLE: Fetching from a scrollable cursor may overwrite user-specified buffer and corrupt memory -DESCRIPTION: Engine did overwrite the user-specified buffer with four more bytes than expected that could corrupt the caller memory. +DESCRIPTION: + Engine did overwrite the user-specified buffer with four more bytes than expected that could corrupt the caller memory. + Discussed between dimitr, pcisar and pzotov, see letters of 29-30 NOV 2021, + subj: "firebird-driver & scrollable cursors // misc. tests, requested by dimitr" NOTES: [18.07.2024] pzotov - 1. Apropriate script without QA plugin caused crash of Python up to 5.0.0.325 (30-nov-2021). - Snapshot 5.0.0.326-fd6bf8d (01-dec-2021 08:44) was fixed but only if we run script not under QA plugin. - 2. Despite that fix (fd6bf8d404068417552f9c8d7ae2e232fa860005, 01-dec-2021 11:45), actually all subsequent - FB snapshots still had a problem until 10-jan-2023: running this test on them caused BUGCHECK + 1. ### ACHTUNG ### + Old snapshots (before 5.0.0.890-aa847a7) must be checked with usage "--disable-db-cache" command switch for pytest! + Otherwise one may FALSE failure (bugcheck) with: "internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 293)" - 3. Eventually problem was solved 10-JAN-2023: - 5.0.0.890-a6ce0ec -- crash - 5.0.0.890-aa847a7 -- OK - 4. Discussed between dimitr, pcisar and pzotov, see letters of 29-30 NOV 2021, - subj: "firebird-driver & scrollable cursors // misc. tests, requested by dimitr" - 5. Problem appeared only for column with width = 32765 characters, thus DB charset must be single-byte, e.g. win1251 etc. + + 2. Initial problem related to cursor operation was found in 5.0.0.316 and result depends on CONNECTION PROTOCOL(!): + 1.1. For REMOTE protocol cur.fetch_first() raised "firebird.driver.types.DatabaseError: feature is not supported" + 1.2. For LOCAL protocol Python crashed with console output: + ============== + Current thread 0x00004ad0 (most recent call first): + File "C:/FBTESTING/qa/firebird-qa/tests/bugs/gh_7056_test.py", line 74 in test_1 + File "C:/Python3x/Lib/site-packages/_pytest/python.py", line 194 in pytest_pyfunc_call + File "C:/Python3x/Lib/site-packages/pluggy/_callers.py", line 102 in _multicall + ... + File "C:/Python3x/Lib/site-packages/_pytest/config/__init__.py", line 198 in console_main + File "C:/Python3x/Scripts/pytest.exe/__main__.py", line 7 in + File "", line 88 in _run_code + File "", line 198 in _run_module_as_main + ============== + + Problem with "firebird.driver.types.DatabaseError: feature is not supported" has been fixed in 5.0.0.320, commit: + 5a5a2992f78c1af9408091a0bd3fff50e0bc5d6a (26-nov-2021 09:11) + "Better boundary checks, code unification, removed end-of-stream errors when fetching past EOF / beyond BOF (as per SQL spec)" + Problem with Python crash did exist up to 5.0.0.325 (30-nov-2021) and has been fixed in 5.0.0.326-fd6bf8d (01-dec-2021 08:44) + 3. Problem appeared only for column with width = 32765 characters, thus DB charset must be single-byte, e.g. win1251 etc. Otherwise (with default charset = 'utf8') this test will fail with: "SQLSTATE = 54000 / ... or string truncation / -Implementation limit exceeded" + 4. We have to use ustom driver-config object must be used for DPB because TWO protocols are checked here: LOCAL and REMOTE. Checked on 6.0.0.396, 5.0.1.1440 """ import pytest from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol, DatabaseError +import re N_WIDTH = 32765 init_script = f""" - recreate table ts(id int primary key, s varchar({N_WIDTH})); + create table ts(id int primary key, s varchar({N_WIDTH})); insert into ts(id,s) values( 1, lpad('', {N_WIDTH}, 'A') ); commit; """ db = db_factory(init=init_script, charset = 'win1251') act = python_act('db', substitutions=[('[ \t]+', ' ')]) +def strip_white(value): + value = re.sub('(?m)^\\s+', '', value) + return re.sub('(?m)\\s+$', '', value) + @pytest.mark.scroll_cur @pytest.mark.version('>=5.0.0') def test_1(act: Action, capsys): - success_msg = 'COMPLETED.' - with act.db.connect() as con: - cur = con.cursor() - cur.open('select id, s from ts order by id') - cur.fetch_first() - print(success_msg) + srv_cfg = driver_config.register_server(name = 'test_srv_gh_7056', config = '') + actual_out = expected_out = '' + for protocol_name in ('local', 'remote'): + + db_cfg_name = f'tmp_7056_{protocol_name}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = None if protocol_name == 'local' else NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + + db_con_string = str(act.db.db_path) if protocol_name == 'local' else act.db.dsn + + success_msg = f'Protocol: {protocol_name} - COMPLETED.' + expected_out += success_msg + '\n' + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.open('select id, s from ts order by id') + cur.fetch_first() + print(success_msg) + except DatabaseError as e: + print(e.__str__()) - act.expected_stdout = f"{success_msg}" - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout + actual_out += capsys.readouterr().out + '\n' + assert expected_out != '' and strip_white(actual_out) == strip_white(expected_out) From 2151187823178a3ccec132467fa06e7b2ad73202 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 18 Jul 2024 21:26:24 +0300 Subject: [PATCH 0078/1064] Added/Updated tests\bugs\gh_7056_test.py: Replaced non-asci character that was occasionally typed --- tests/bugs/gh_7056_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_7056_test.py b/tests/bugs/gh_7056_test.py index 157a6f52..8bc1e7ba 100644 --- a/tests/bugs/gh_7056_test.py +++ b/tests/bugs/gh_7056_test.py @@ -37,7 +37,7 @@ 3. Problem appeared only for column with width = 32765 characters, thus DB charset must be single-byte, e.g. win1251 etc. Otherwise (with default charset = 'utf8') this test will fail with: "SQLSTATE = 54000 / ... or string truncation / -Implementation limit exceeded" - 4. We have to use ustom driver-config object must be used for DPB because TWO protocols are checked here: LOCAL and REMOTE. + 4. We have to use custom driver-config object must be used for DPB because TWO protocols are checked here: LOCAL and REMOTE. Checked on 6.0.0.396, 5.0.1.1440 """ From 4070f25076937e83b55ec02a4b454ed931a6bae9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 19 Jul 2024 16:19:07 +0300 Subject: [PATCH 0079/1064] Added/Updated tests\functional\tabloid\test_90129c6d.py: Checked on 6.0.0.396, 5.0.1.1440. See notes. --- tests/functional/tabloid/test_90129c6d.py | 164 ++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 tests/functional/tabloid/test_90129c6d.py diff --git a/tests/functional/tabloid/test_90129c6d.py b/tests/functional/tabloid/test_90129c6d.py new file mode 100644 index 00000000..4ca919e5 --- /dev/null +++ b/tests/functional/tabloid/test_90129c6d.py @@ -0,0 +1,164 @@ +#coding:utf-8 + +""" +ID: issue-90129c6d +ISSUE: https://github.com/FirebirdSQL/firebird/commit/90129c6d3ebd5d1c9a7b44d287a4791dffcd031e +TITLE: Scrollable cursors. Fixed isBof/isEof when the prefetch is active +DESCRIPTION: + is_bof()/is_eof() could became True much earlier than actual position of cursor did come to BOF/EOF. + This occurred on fetch_prior() / fetch_next() calls and caused wrong result for counting number of + processed rows. + Discussed with dimitr, see letters with subj = "firebird-driver & scrollable cursors". + Dates: 27.11.2021 21:20, 28.11.2021 19:00, 29.11.2021 07:40 +NOTES: + [19.07.2024] pzotov + 1. No ticket has been created for described problem. + Problem was fixed 28.11.2021 at 16:09, commit #90129c6d. + Confirmed bug on 5.0.0.321 (28.11.2021). Fixed in 5.0.0.324 (29.11.2021). + 2. Initial test contained too big values for check: + N_ROWS = 10000 + N_WIDTH = 32765 + LOOP_COUNT = 1000 + They can be safely replaced with minimal possible values in order to see difference before and after fix. + 3. NOTE that argument passed to cur.stream_blobs.append() must be equal to the name of blob column as it is + stored in RDB$ tables, i.e. in uppercase. Because of that, variable 'BLOB_FLD_NAME' is used instead of + repeating blob column name in DDL and cur.stream_blobs.append(). + 4. Custom driver-config object must be used for DPB because two values of WireCrypt parameter must be checked: + Enabled and Disabled (see 'w_crypt'). + + Checked on 6.0.0.396, 5.0.1.1440. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol +import time + +db = db_factory() +act = python_act('db') + +N_ROWS = 1 +N_WIDTH = 1 +LOOP_COUNT = 2 +BLOB_FLD_NAME = 'BINARY_DATA' + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + srv_cfg = driver_config.register_server(name = 'test_90129c6d_srv', config = '') + + for w_crypt in ('Enabled', 'Disabled'): + db_cfg_name = f'test_90129c6d_wcrypt_{w_crypt}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + WireCrypt = w_crypt + """ + + for suitable_for_compression in (0,1): + if suitable_for_compression: + data_dml = f""" + execute block as + declare n int = {N_ROWS}; + begin + while ( n > 0 ) do + begin + insert into ts(id,{BLOB_FLD_NAME}) values(:n, lpad('', {N_WIDTH}, 'A')); + n = n - 1; + end + end + """ + else: + data_dml = f""" + execute block as + declare n int = {N_ROWS}; + declare n_wid int = {N_WIDTH}; + declare encrypted_text varchar({N_WIDTH}) character set octets; + declare encr_addition varchar(16) character set octets; + begin + while (n > 0) do + begin + encrypted_text = ''; + encr_addition = ''; + while ( 1 = 1 ) do + begin + encr_addition = gen_uuid(); + if ( octet_length(encrypted_text) < n_wid - octet_length(encr_addition) ) then + encrypted_text = encrypted_text || trim(encr_addition); + else + begin + encrypted_text = encrypted_text || left(encr_addition, n_wid - octet_length(encrypted_text)); + leave; + end + end + insert into ts(id,{BLOB_FLD_NAME}) values(:n, :encrypted_text); + n = n - 1; + end + end + """ + + init_sql = f""" + recreate table ts(id int primary key, {BLOB_FLD_NAME} blob) + ^ + commit + ^ + {data_dml} + ^ + commit + ^ + """ + + with act.db.connect() as con: + cur = con.cursor() + for x in init_sql.split("^"): + s = x.lower().strip() + if s == "commit": + con.commit() + elif s: + cur.execute(s) + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + assert (True if w_crypt else False) == con.info.is_encrypted(), f'Value of {con.info.is_encrypted()=} not equals to required: {w_crypt=}' + + cur = con.cursor() + cur.stream_blobs.append(BLOB_FLD_NAME.upper()) + cur.open(f'select id, {BLOB_FLD_NAME} from ts order by id') + + for iter_no in range(LOOP_COUNT): + cnt_fwrd=0 + while True: + fetched_row_data = cur.fetch_next() + if cur.is_eof(): + break + v_id, v_blob_data = fetched_row_data + with v_blob_data: + v_blob_data.read() + cnt_fwrd += 1 + + cnt_back=0 + while True: + fetched_row_data = cur.fetch_prior() + if cur.is_bof(): + break + v_id, v_blob_data = fetched_row_data + with v_blob_data: + v_blob_data.read() + cnt_back += 1 + + print(f'{w_crypt=}, {suitable_for_compression=}, {iter_no=}: {cnt_fwrd=}, {cnt_back=}') + + act.expected_stdout = """ + w_crypt='Enabled', suitable_for_compression=0, iter_no=0: cnt_fwrd=1, cnt_back=1 + w_crypt='Enabled', suitable_for_compression=0, iter_no=1: cnt_fwrd=1, cnt_back=1 + w_crypt='Enabled', suitable_for_compression=1, iter_no=0: cnt_fwrd=1, cnt_back=1 + w_crypt='Enabled', suitable_for_compression=1, iter_no=1: cnt_fwrd=1, cnt_back=1 + w_crypt='Disabled', suitable_for_compression=0, iter_no=0: cnt_fwrd=1, cnt_back=1 + w_crypt='Disabled', suitable_for_compression=0, iter_no=1: cnt_fwrd=1, cnt_back=1 + w_crypt='Disabled', suitable_for_compression=1, iter_no=0: cnt_fwrd=1, cnt_back=1 + w_crypt='Disabled', suitable_for_compression=1, iter_no=1: cnt_fwrd=1, cnt_back=1 + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From fc56df7734b8fbb1e3f24d0990b8db54d2360dbc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 19 Jul 2024 16:20:18 +0300 Subject: [PATCH 0080/1064] Added/Updated tests\functional\tabloid\test_90129c6d.py: Added mark 'scroll_cur' for including into the set of tests that deal with scrollable cursor --- tests/functional/tabloid/test_90129c6d.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/tabloid/test_90129c6d.py b/tests/functional/tabloid/test_90129c6d.py index 4ca919e5..41d2a173 100644 --- a/tests/functional/tabloid/test_90129c6d.py +++ b/tests/functional/tabloid/test_90129c6d.py @@ -42,6 +42,7 @@ LOOP_COUNT = 2 BLOB_FLD_NAME = 'BINARY_DATA' +@pytest.mark.scroll_cur @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): From 68ed071f41d8ab5a952a4b75b84b6b4407fe9c45 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 19 Jul 2024 16:20:56 +0300 Subject: [PATCH 0081/1064] Added/Updated tests\bugs\gh_7056_test.py: minor change in comments --- tests/bugs/gh_7056_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_7056_test.py b/tests/bugs/gh_7056_test.py index 8bc1e7ba..7a8982b9 100644 --- a/tests/bugs/gh_7056_test.py +++ b/tests/bugs/gh_7056_test.py @@ -37,7 +37,7 @@ 3. Problem appeared only for column with width = 32765 characters, thus DB charset must be single-byte, e.g. win1251 etc. Otherwise (with default charset = 'utf8') this test will fail with: "SQLSTATE = 54000 / ... or string truncation / -Implementation limit exceeded" - 4. We have to use custom driver-config object must be used for DPB because TWO protocols are checked here: LOCAL and REMOTE. + 4. Custom driver-config object must be used for DPB because TWO protocols are checked here: LOCAL and REMOTE. Checked on 6.0.0.396, 5.0.1.1440 """ From f5b7ac0ec171bbab9b3fe27982bb1f7e199eb4bd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 19 Jul 2024 18:33:33 +0300 Subject: [PATCH 0082/1064] Added/Updated tests\functional\tabloid\test_c8849946.py: Checked on 6.0.0.396, 5.0.1.1440. See notes. --- tests/functional/tabloid/test_c8849946.py | 107 ++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 tests/functional/tabloid/test_c8849946.py diff --git a/tests/functional/tabloid/test_c8849946.py b/tests/functional/tabloid/test_c8849946.py new file mode 100644 index 00000000..2504fe03 --- /dev/null +++ b/tests/functional/tabloid/test_c8849946.py @@ -0,0 +1,107 @@ +#coding:utf-8 + +""" +ID: issue-c8849946 +ISSUE: https://github.com/FirebirdSQL/firebird/commit/c884994653523d7d6d614075af45c7ecf338008e +TITLE: Scrollable cursors. Inconsistent cursor repositioning +DESCRIPTION: + Test case provided by dimitr, see letters with subj = "firebird-driver & scrollable cursors". + Date: 01.12.2021 08:20. +NOTES: + [19.07.2024] pzotov + 1. No ticket has been created for described problem. + Problem was fixed 30.11.2021 at 16:55, commit = push = c8849946 + 2. Confirmed bug on 5.0.0.324. Fixed in 5.0.0.325-c884994 + Checked on 6.0.0.396, 5.0.1.1440. +""" + +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db') + +N_ROWS = 1010 +############# + +def print_row(row, cur = None): + if row: + print(f"{row[0]}") + if cur and (cur.is_bof() or cur.is_eof()): + print('### STRANGE BOF/EOR WHILE SOME DATA CAN BE SEEN ###') + else: + msg = '*** NO_DATA***' + if cur: + msg += ' BOF=%r EOF=%r' % ( cur.is_bof(), cur.is_eof() ) + print(msg) + +#---------------------------- + +@pytest.mark.scroll_cur +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + cur = con.cursor() + cur.open(f'select row_number()over() as id from rdb$types, rdb$types rows {N_ROWS}') + + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + + print_row(cur.fetch_last(), cur) + print_row(cur.fetch_next(), cur) + + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_prior(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + print_row(cur.fetch_next(), cur) + + + act.expected_stdout = """ + 1 + 2 + 3 + 2 + 1 + *** NO_DATA*** BOF=True EOF=False + 1 + 2 + 3 + 2 + 1 + *** NO_DATA*** BOF=True EOF=False + 1010 + *** NO_DATA*** BOF=False EOF=True + 1010 + 1009 + 1008 + 1009 + 1010 + *** NO_DATA*** BOF=False EOF=True + 1010 + 1009 + 1008 + 1009 + 1010 + *** NO_DATA*** BOF=False EOF=True + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From e98d03db83e040bc1374a23700475091ed36968e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 21 Jul 2024 00:01:46 +0300 Subject: [PATCH 0083/1064] Added/Updated tests\functional\tabloid\test_6cfc9b5d.py: Checked on 6.0.0.396, 5.0.1.1440 (both SS/CS). See notes. --- tests/functional/tabloid/test_6cfc9b5d.py | 410 ++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 tests/functional/tabloid/test_6cfc9b5d.py diff --git a/tests/functional/tabloid/test_6cfc9b5d.py b/tests/functional/tabloid/test_6cfc9b5d.py new file mode 100644 index 00000000..a4f76f01 --- /dev/null +++ b/tests/functional/tabloid/test_6cfc9b5d.py @@ -0,0 +1,410 @@ +#coding:utf-8 +""" +ID: issue-6cfc9b5d +ISSUE: https://github.com/FirebirdSQL/firebird/commit/6cfc9b5d7dc343295968cc4545c6fa184966cfc9 +TITLE: Scrollable cursors. Automated test with randomly generated mission for positioning. +DESCRIPTION: + Test verifies commit "Fixed the remaining issues with scrollable cursor re-positioning" (06.12.2021 07:47). + We generate data (see usage of table 'TEST' and SP sp_generate_test_data), and this data (see TEST.BINARY_DATA) + can be one of following type: + * NULL in every record; + * be compressible with MAX ratio (string like 'AAA....AAA'); + * be absolutely incompressible (UUID-based values). + Number of rows in the TEST table is defined by settings N_ROWS + Number of operations for change cursor position is defined by settings FETCH_OPERATIONS_TO_PERFORM + + Then we perform miscelaneous operations that change position of scrollable cursor (on random basis). + These operations are stored in the table 'job_for_cursor_movement', see call of SP sp_make_job_for_cursor_movement. + Outcome of that: randomly generated operations are stored in the table 'move_operations'. + + Result of positioning (value of obtained ID) is compared with expected one. + These actions are performed for all possible combinations of the following criteria: + * data compressibility (see 'a_suitable_for_compression') + * connection protocol ('local' or 'remote') + * value of WireCrypt parameter (Enabled or DIsabled) +NOTES: + [20.07.2024] pzotov + 1. Values of TEST.ID must start with 1 rather rthan 0. + 2. Custom driver-config object must be used for DPB because two values of WireCrypt parameter must be checked: + Enabled and Disabled (see 'w_crypt'). + Also, we verify result for two protocols that are used for connection: local and remote (INET). + + Checked on 6.0.0.396, 5.0.1.1440 (both SS/CS). +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol +import time + +######################### +### S E T T I N G S ### +######################### +N_ROWS = 20 +N_WIDTH = 32765 +FETCH_OPERATIONS_TO_PERFORM = 100 +#------------------------- + +init_script = f""" + create or alter procedure sp_generate_test_data as begin end; + create or alter procedure sp_make_job_for_cursor_movement as begin end; + create or alter view v_fetch_expected_data as select 1 x from rdb$database; + create or alter view v_fetch_job as select 1 x from rdb$database; + + recreate table move_operations(nm varchar(10)); + insert into move_operations(nm) values('first'); + insert into move_operations(nm) values('last'); + insert into move_operations(nm) values('next'); + insert into move_operations(nm) values('prior'); + insert into move_operations(nm) values('absolute'); + insert into move_operations(nm) values('relative'); + commit; + + recreate table job_for_cursor_movement( + rn int primary key + ,nm varchar(10) + ,arg_n int + ,cnt int + ,id_min int + ,id_max int + ,bof int + ,eof int + ,id_expected int + -- ,constraint job_valid check( nm in ('absolute', 'relative') and arg_n is not null ) + ) + ; + + --------------------- + recreate table test( id int primary key, binary_data varchar( {N_WIDTH} ) character set octets ); + comment on table test is q'#Textual column width was substitued from .py script, see variable 'N_WIDTH' there.#' + ; + commit; + --------------------- + + create or alter view v_fetch_job as + with + i as ( + select + count(*)+1 as cnt + ,min(id) as id_min + ,max(id) as id_max + from test + ) + ,a as ( + select + f.nm + ,iif(f.nm in ('absolute', 'relative'), 1, null) as def_sign + ,i.cnt + ,i.id_min + ,i.id_max + ,iif(f.nm = 'absolute', 0, -i.cnt) as rnd_min + ,iif(f.nm = 'absolute', i.cnt, 2*i.cnt) as rnd_max + from move_operations f + cross join i + ) + select + row_number()over(order by rand()) as rn + ,a.nm + ,a.def_sign * cast(a.rnd_min + rand() * a.rnd_max as int) as arg_n + ,a.cnt + ,a.id_min + ,a.id_max + from a + cross join(select rand() as x from rdb$types a, rdb$types b rows 1000) b + ; + + ---------------------------- + create or alter view v_fetch_expected_data as + with recursive + r as ( + select + rn + ,cast(null as int) as id_expect_bak + ,nm + ,arg_n + ,case nm + when 'first' then id_min + when 'last' then id_max + when 'prior' then bof + when 'next' then id_min + when 'relative' then iif( id_min + arg_n - 1 > id_max, eof, iif( id_min + arg_n <= id_min, bof, id_min + arg_n - 1 ) ) + when 'absolute' then -- iif( arg_n > id_max, eof, iif( id_min + arg_n <=0, bof, id_min + arg_n ) ) + case + when b.arg_n > b.id_max then b.eof + when b.arg_n > 0 then b.id_min + (b.arg_n-1) + when b.arg_n = 0 or b.arg_n < -b.cnt then b.bof + else -- b.arg_n between -b.cnt and -1 + b.id_max + b.arg_n - 1 + end + end as id_expected + ,cnt + ,id_min + ,id_max + ,bof + ,eof + from job_for_cursor_movement b + where rn = 1 + + UNION ALL + + select + x.rn + ,r.id_expected as id_expect_bak + ,x.nm + ,x.arg_n + ,case x.nm + when 'first' then r.id_min + when 'last' then r.id_max + when 'prior' then iif(r.id_expected = r.eof, r.id_max, iif( r.id_expected <= r.id_min, r.bof, r.id_expected - 1 ) ) + when 'next' then iif( r.id_expected = r.bof, r.id_min, iif( r.id_expected >= r.id_max, r.eof, r.id_expected + 1 ) ) + when 'relative' then -- iif( r.id_expected + x.arg_n > r.id_max, r.eof, iif( r.id_expected + x.arg_n < r.id_min, r.bof, r.id_expected + x.arg_n ) ) + case + when r.id_expected = r.bof then iif(x.arg_n <= 0, r.bof, iif(x.arg_n >= r.cnt, r.eof, x.arg_n)) + when r.id_expected = r.eof then iif(x.arg_n >= 0, r.eof, iif(abs(x.arg_n) >= r.cnt, r.bof, r.id_max + 1 - abs(x.arg_n))) + else iif( r.id_expected + x.arg_n > r.id_max, r.eof, iif( r.id_expected + x.arg_n < r.id_min, r.bof, r.id_expected + x.arg_n ) ) + end + when 'absolute' then + case + when x.arg_n > r.id_max then r.eof + when x.arg_n > 0 then r.id_min + (x.arg_n-1) + when x.arg_n = 0 or x.arg_n < -r.cnt then r.bof + else -- x.arg_n between -r.cnt and -1 + r.id_max + x.arg_n - 1 + end + end as id_expected + ,r.cnt + ,r.id_min + ,r.id_max + ,r.bof + ,r.eof + from r + join job_for_cursor_movement x on r.rn + 1 = x.rn + --where x.rn <= 3 + + ) + select * from r + ; + ----------------------------- + + set term ^; + create or alter procedure sp_make_job_for_cursor_movement(a_rows_to_add int = 20) as + declare cnt int; + declare bof int = -2147483648; + declare eof int = 2147483647; + begin + delete from job_for_cursor_movement; + select count(*) from test into cnt; + + insert into job_for_cursor_movement( + rn, + nm, + arg_n, + cnt, + id_min, + id_max, + bof, + eof + ) + select + rn, + nm, + arg_n, + cnt, + id_min, + id_max, + :bof, + :eof + from v_fetch_job + rows :a_rows_to_add + ; + + merge into job_for_cursor_movement t + using (select rn, id_expected from v_fetch_expected_data) s on t.rn = s.rn + when MATCHED then update set t.id_expected = s.id_expected + ; + + end + ^ + create or alter procedure sp_generate_test_data(a_suitable_for_compression smallint, a_rows int) as + declare i int = 1; + declare dummy int; + declare s varchar({N_WIDTH}); + declare uuid_text varchar({N_WIDTH}) character set octets; + declare uuid_addi varchar(16) character set octets; + begin + delete from test; + select count(*) from test into dummy; + s = iif(a_suitable_for_compression = 0, null, lpad('', {N_WIDTH}, 'A')); + if (a_suitable_for_compression in (0,1) ) then + begin + while( i <= a_rows ) do + begin + insert into test(id, binary_data) values(:i, :s); + i = i + 1; + end + end + else + begin + -- generate NON-compressible data + while (i <= a_rows) do + begin + uuid_text = ''; + uuid_addi = ''; + while ( 1=1 ) do + begin + uuid_addi = gen_uuid(); + if ( octet_length(uuid_text) < {N_WIDTH} - octet_length(uuid_addi) ) then + uuid_text = uuid_text || trim(uuid_addi); + else + begin + uuid_text = uuid_text || left(uuid_addi, {N_WIDTH} - octet_length(uuid_text)); + leave; + end + + + end + insert into test(id,binary_data) values( :i, :uuid_text); + --execute statement ('insert into test(id,binary_data) values(?, ?)') ( :i, :uuid_text); + i = i + 1; + end + end + end + ^ + set term ;^ + commit; +""" + +db = db_factory(init = init_script, charset='win1251') +act = python_act('db') + +#---------------------------- + +def print_row(row, cur = None): + if row: + print(f"{row[0]}") + if cur and (cur.is_bof() or cur.is_eof()): + print('### STRANGE BOF/EOR WHILE SOME DATA CAN BE SEEN ###') + else: + msg = '*** NO_DATA***' + if cur: + msg += ' BOF=%r EOF=%r' % ( cur.is_bof(), cur.is_eof() ) + print(msg) + +#---------------------------- + +@pytest.mark.scroll_cur +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, capsys): + + for a_suitable_for_compression in (0,1,2): + move_ops = {} + with act.db.connect() as con: + cur = con.cursor() + cur.callproc('sp_generate_test_data', (a_suitable_for_compression, N_ROWS)) + con.commit() + cur.callproc('sp_make_job_for_cursor_movement', (FETCH_OPERATIONS_TO_PERFORM,)) + con.commit() + + cur.execute('select rn, nm, arg_n, id_expected from job_for_cursor_movement order by rn') + for r in cur: + move_ops[ r[0] ] = (r[1], '' if r[2] == None else r[2], r[3]) + + # result: + # table 'test' contains rows with data that has character appropriated to a_suitable_for_compression value + # table 'job_for_cursor_movement' contains rows with randomly generated 'jobs' for cursor positioning. + # column job_for_cursor_movement.id_expected has EXPECTED values for ID after each position operation against table 'test'; we will compare ID with it. + + # Example of move_ops: + # 1 : oper = fetch_last , id_expected: 19 + # 2 : oper = fetch_first , id_expected: 0 + # 3 : oper = fetch_relative(5) , id_expected: 5 + # 4 : oper = fetch_relative(16) , id_expected: 2147483647 + # ... + # 96 : oper = fetch_absolute(2) , id_expected: 1 + # 97 : oper = fetch_prior , id_expected: 0 + # 98 : oper = fetch_relative(5) , id_expected: 5 + # 99 : oper = fetch_relative(-9) , id_expected: -2147483648 + # 100 : oper = fetch_absolute(10) , id_expected: 9 + + srv_cfg = driver_config.register_server(name = f'test_6cfc9b5d_srv_{a_suitable_for_compression}', config = '') + + for protocol_name in ('local', 'remote'): + for w_crypt in ('Enabled', 'Disabled'): + + PASSED_MSG = f'{a_suitable_for_compression=}, {protocol_name=}, {w_crypt=}: PASSED.' + + db_cfg_name = f'test_90129c6d_wcrypt_{a_suitable_for_compression}_{w_crypt}_{protocol_name}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = None if protocol_name == 'local' else NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + WireCrypt = w_crypt + """ + + details_lst = [] + chk_retcode = 0 + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + + cur = con.cursor() + cur.open("select id, binary_data from test order by id") + + for k,v in sorted(move_ops.items()): + crow = None + chk_val = None + f_kind = v[0].strip() + if f_kind == 'prior': + crow = cur.fetch_prior() + elif f_kind == 'next': + crow = cur.fetch_next() + elif f_kind == 'first': + crow = cur.fetch_first() + elif f_kind == 'last': + crow = cur.fetch_last() + elif f_kind == 'relative': + crow = cur.fetch_relative( v[1] ) + elif f_kind == 'absolute': + crow = cur.fetch_absolute( v[1] ) + + wrong_found_msg = '' + if crow: + chk_val = crow[0] + if cur.is_bof() or cur.is_eof(): + wrong_found_msg += ('One of BOF/EOF is true (BOF=%r, EOF=%r), but cursor returns data: %d' % (cur.is_bof(), cur.is_eof(), crow[0])) + else: + if cur.is_bof(): + chk_val = -2147483648 + elif cur.is_eof(): + chk_val = 2147483647 + else: + wrong_found_msg += '!! No data from cursor but also neither BOF nor EOF.' + + msg = ''.join( + ( '%5d ' % k + ,'+++ passed +++' if wrong_found_msg == '' and v[2] == chk_val else '## MISMATCH ##' + ,f'fetch oper: {f_kind},{v[1]}; id_expected: {v[2]}' + ,f'; id_actual: {chk_val};' + ,'BOF' if cur.is_bof() else '' + ,'EOF' if cur.is_eof() else '' + ) + ) + details_lst.append(msg) + + if not v[2] == chk_val or wrong_found_msg: + chk_retcode = 1 + print(f'{a_suitable_for_compression=}, {protocol_name=}, {w_crypt=}: FAILED.') + for x in details_lst: + print(x) + break + + if chk_retcode == 0: + print(PASSED_MSG) + else: + print('###############') + print('### F A I L ###') + print('###############') + + act.expected_stdout = PASSED_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 764caf92a14afa3adf7ee64a9743f7028e477fdc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 21 Jul 2024 11:03:56 +0300 Subject: [PATCH 0084/1064] Added/Updated tests\bugs\gh_7647_test.py: Problem with 6.x has been fixed in 6.0.0.346, commit 17b007d1. Removed upper limit restriction for major version. --- tests/bugs/gh_7647_test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_7647_test.py b/tests/bugs/gh_7647_test.py index 064948ef..07d243ec 100644 --- a/tests/bugs/gh_7647_test.py +++ b/tests/bugs/gh_7647_test.py @@ -12,6 +12,11 @@ "ValueError: Incorrect ARRAY field value." raises on firebird.driver: 1.10.1 / firebird-qa-0.19.2 Added restriction for major versions that are allowed to be checked: currently only 3.x and 4.x. See also: https://github.com/FirebirdSQL/firebird/issues/7862 + + [21.07.2024] pzotov + Problem with 6.x has been fixed in 6.0.0.346, commit date 07.05.2024: + https://github.com/FirebirdSQL/firebird/commit/17b007d14f8ccc6cfba0d63a3b2f21622ced20d0 + Removed upper limit restriction for major version. """ import pytest @@ -25,7 +30,7 @@ act = python_act('db') -@pytest.mark.version('>=3.0.12,<5.0') +@pytest.mark.version('>=3.0.12') def test_1(act: Action, capsys): with act.db.connect() as con: cur = con.cursor() From c0c400cb1194dad0eca148482aaf1a639aeb7f8d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 21 Jul 2024 17:18:26 +0300 Subject: [PATCH 0085/1064] Added/Updated tests\bugs\gh_7188_test.py: Checked on 6.0.0.396, 5.0.1.1440, 4.0.53127. --- tests/bugs/gh_7188_test.py | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/bugs/gh_7188_test.py diff --git a/tests/bugs/gh_7188_test.py b/tests/bugs/gh_7188_test.py new file mode 100644 index 00000000..cf17268a --- /dev/null +++ b/tests/bugs/gh_7188_test.py @@ -0,0 +1,85 @@ +#coding:utf-8 + +""" +ID: issue-7188 +ISSUE: 7188 +TITLE: Memory leak in GDS32.DLL(FBClient.DLL), when multi-database transaction has done +DESCRIPTION: + Test obtains PID of currently running Python script which serves as CLIENT for server. + Then we get values of RSS and VMS by invoking client_process.memory_info() and store them. + After that, we use DistributedTransactionManager instance for making two connections to different + databases and run times Tx start and commit (in loop). + Finally, we get again RSS and VMS values for currently running Python process, and compare them + with initially stored ones. + Ratio between appropriate final and initial values of RSS and VMS must not exceed thresholds + defined by RSS_MAX_DIFF and VMS_MAX_DIFF. +NOTES: + [21.07.2024] pzotov + Confirmed memory leak in the CLIENT process (i.e. python.exe) when running test on: + * 5.0.0.511 (09-jun-2022): + memo_rss_list=[46988, 54192] diff = 1.15332 + memo_vms_list=[37048, 44228] diff = 1.19380 + * 4.0.2.2776 (10.06.2022): + memo_rss_list=[47248, 54456] diff = 1.15255 + memo_vms_list=[37240, 44424] diff = 1.19291 + Aftef fix: + * 5.0.1.514: + memo_rss_list=[47164, 47184] diff = 1.000424 + memo_vms_list=[37200, 37200] no_diff + * 4.0.2.2779: + memo_rss_list=[47256, 47272] diff = 1.0003386 + memo_vms_list=[37172, 37172] no_diff + Checked on 6.0.0.396, 5.0.1.1440, 4.0.53127. + Thanks to Vlad for suggestions about test implementation. +""" +import os +import pytest +from firebird.qa import * +from firebird.driver import DistributedTransactionManager, tpb, Isolation +import psutil + +db1 = db_factory(filename='core_7188_a.fdb') +db2 = db_factory(filename='core_7188_b.fdb') + +tmp_user1 = user_factory('db1', name='tmp$7188_1', password='123') +tmp_user2 = user_factory('db2', name='tmp$7188_2', password='456') + +act1 = python_act('db1') +act2 = python_act('db2') + +LOOP_COUNT = 10000 +CUSTOM_TPB = tpb(isolation = Isolation.READ_COMMITTED) +RSS_MAX_DIFF = 1.003 +VMS_MAX_DIFF = 1.001 +PASSED_MSG = 'OK' + +@pytest.mark.version('>=4.0.2') +def test_1(act1: Action, act2: Action, tmp_user1: User, tmp_user2: User, capsys): + dt_list = [] + memo_rss_list = [] + memo_vms_list = [] + client_process = psutil.Process( os.getpid() ) + + memo_rss_list.append(int(client_process.memory_info().rss / 1024)) + memo_vms_list.append(int(client_process.memory_info().vms / 1024)) + with act1.db.connect(user = tmp_user1.name, password = tmp_user1.password) as con1, \ + act2.db.connect(user = tmp_user2.name, password = tmp_user2.password) as con2: + + for i in range(LOOP_COUNT): + dt = DistributedTransactionManager([con1, con2]) + dt.begin(tpb = CUSTOM_TPB) + dt.commit() + + memo_rss_list.append(int(client_process.memory_info().rss / 1024)) + memo_vms_list.append(int(client_process.memory_info().vms / 1024)) + + if memo_rss_list[1] / memo_rss_list[0] < RSS_MAX_DIFF and memo_vms_list[1] / memo_vms_list[0] < VMS_MAX_DIFF: + print(PASSED_MSG) + else: + print('client_process.memory_info(): ratio of RSS and/or VMS values exceeds threshold.') + print(f'{memo_rss_list=}, ratio: {memo_rss_list[1] / memo_rss_list[0]:.3f}, {RSS_MAX_DIFF=:.3f}') + print(f'{memo_vms_list=}, ratio: {memo_vms_list[1] / memo_vms_list[0]:.3f}, {VMS_MAX_DIFF=:.3f}') + + act1.expected_stdout = PASSED_MSG + act1.stdout = capsys.readouterr().out + assert act1.clean_stdout == act1.clean_expected_stdout From cafd101681e7821aa45e396ef1bcc6d5b3b78c27 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 21 Jul 2024 19:25:46 +0300 Subject: [PATCH 0086/1064] Added/Updated tests\bugs\gh_6954_test.py: Checked on 6.0.0.396, 5.0.1.1440, 4.0.53127. --- tests/bugs/gh_6954_test.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/bugs/gh_6954_test.py diff --git a/tests/bugs/gh_6954_test.py b/tests/bugs/gh_6954_test.py new file mode 100644 index 00000000..614c0bd2 --- /dev/null +++ b/tests/bugs/gh_6954_test.py @@ -0,0 +1,37 @@ +#coding:utf-8 + +""" +ID: issue-6954 +ISSUE: 6954 +TITLE: Add fb_info_protocol_version information request to Attachment::getInfo(). +DESCRIPTION: + We attempt to obtain DbInfoCode.PROTOCOL_VERSION and print only the fact that we could do that + (instead of its concrete value which, of course can change). +NOTES: + Improvement was committed: + * in FB 4.x: 15.09.2021 18:25, cb2d8dfb (4.0.1.2602) + * in FB 5.x: 09.09.2021 17:27, 18d59a5e (5.0.0.196) + Before these snapshots attempt to obtain protocol version caused error: + ====== + raise InterfaceError("An error response was received") + firebird.driver.types.InterfaceError: An error response was received + ====== + + Checked on 6.0.0.396, 5.0.1.1440, 4.0.53127. +""" +import pytest +from firebird.qa import * +from firebird.driver import DbInfoCode + +db = db_factory() +act = python_act('db') #, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0.1') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + print( con.info.get_info(DbInfoCode.PROTOCOL_VERSION) > 0 ) + + act.expected_stdout = 'True' + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From a28fae261ce61afde291bb914a52f772ee2d2a3a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 22 Jul 2024 08:38:45 +0300 Subject: [PATCH 0087/1064] Added/Updated tests\bugs\gh_7056_test.py: minor change: removed unused variable --- tests/bugs/gh_7056_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/bugs/gh_7056_test.py b/tests/bugs/gh_7056_test.py index 7a8982b9..f4af1a79 100644 --- a/tests/bugs/gh_7056_test.py +++ b/tests/bugs/gh_7056_test.py @@ -73,8 +73,6 @@ def test_1(act: Action, capsys): db_cfg_object.protocol.value = None if protocol_name == 'local' else NetProtocol.INET db_cfg_object.database.value = str(act.db.db_path) - db_con_string = str(act.db.db_path) if protocol_name == 'local' else act.db.dsn - success_msg = f'Protocol: {protocol_name} - COMPLETED.' expected_out += success_msg + '\n' From eaa6bd6afa7ab0211eb115d5ca686d77f1bcd0ca Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 22 Jul 2024 13:03:19 +0300 Subject: [PATCH 0088/1064] Added/Updated tests\bugs\gh_6282_test.py: Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127 --- tests/bugs/gh_6282_test.py | 331 +++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 tests/bugs/gh_6282_test.py diff --git a/tests/bugs/gh_6282_test.py b/tests/bugs/gh_6282_test.py new file mode 100644 index 00000000..aa25b771 --- /dev/null +++ b/tests/bugs/gh_6282_test.py @@ -0,0 +1,331 @@ +#coding:utf-8 + +""" +ID: issue-6282 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6282 +TITLE: Add DPB properties for time zone bind and decfloat configuration [CORE6032] +DESCRIPTION: + Test verifies: + * ability to set appropriate DPB parameters described in the ticket; + * actual result of their change (by performing SQL and compare output with expected); + * surviving of changed parameters after 'slter session reset' (i.e. absence of its influence) +NOTES: + [22.07.2024] pzotov + Improvement appeared 07.04.2019 17:56 (2a9f8fa60b327132373cd7ee3f0a0b52e595f6b1), + but actually this test can run only on build after 29.05.2020 (4.0.0.2011) because of + commit https://github.com/FirebirdSQL/firebird/commit/a9cef6d9aeaabc08d8f104230a38345340edf7a2 + ("Implemented CORE-6320: Replace Util methods to get interface pointer by legacy handle with plain functions") + Attempt to run it on earlier snapshots leads to errors: + firebird.driver.types.DatabaseError: invalid statement handle + or + AttributeError: 'iUtil_v2' object has no attribute 'decode_timestamp_tz' + + Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127 +""" +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DecfloatRound, DecfloatTraps, NetProtocol, DatabaseError +import datetime + +init_script = """ + set list on; + /****** + Original: ibm.com/developerworks/ru/library/dm-0801chainani/ + See also: functional/datatypes/test_decfloat_round_modes.py: + round-mode 12.341 12.345 12.349 12.355 12.405 -12.345 + --------------------------------------------------------------- + CEILING 12.35 12.35 12.35 12.36 12.41 -12.34 + UP 12.35 12.35 12.35 12.36 12.41 -12.35 + HALF_UP 12.34 12.35 12.35 12.36 12.41 -12.35 + HALF_EVEN 12.34 12.34 12.35 12.36 12.40 -12.34 + HALF_DOWN 12.34 12.34 12.35 12.35 12.40 -12.34 + DOWN 12.34 12.34 12.34 12.35 12.40 -12.34 + FLOOR 12.34 12.34 12.34 12.35 12.40 -12.35 + REROUND 12.34 12.34 12.34 12.36 12.41 -12.34 + *******/ + + recreate view v_test as select 1 id from rdb$database; + commit; + + recreate table test( + v1 decfloat + ,v2 decfloat + ,v3 decfloat + ,v4 decfloat + ,v5 decfloat + ,v6 decfloat + ,vc decfloat + ,vp decfloat + ,vd decfloat + ,vx computed by (vc * vp / vd) + ,vy computed by (vc * vp / vd) + ) + ; + commit; + + insert into test( v1, v2, v3, v4, v5, v6, vc, vp, vd) + values(12.341, 12.345, 12.349, 12.355, 12.405, -12.345, 1608.90, 5.00, 100.00); + commit; + + recreate view v_test as + select + round(v1, 2) r1, round(v2, 2) r2, round(v3, 2) r3, + round(v4, 2) r4, round(v5, 2) r5, round(v6, 2) r6, + round( vx, 2) as rx, + round( -vy, 2) as ry + from test; + commit; +""" + +db = db_factory(init = init_script) +act = python_act('db') + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + srv_cfg = driver_config.register_server(name = 'srv_cfg_6282', config = '') + + db_cfg_name = f'db_cfg_6282' + + # DatabaseConfig; see PYTHON_HOME/Lib/site-packages/firebird\driver\config.py: + db_cfg_object = driver_config.register_database(name = db_cfg_name) + + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + + ###################################################### + ### c h e c k s e s s i o n t i m e z o n e ### + ###################################################### + # + SELECTED_TIMEZONE = 'Indian/Cocos' + db_cfg_object.session_time_zone.value = SELECTED_TIMEZONE + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + cur = con.cursor() + cur.execute('select current_timestamp from rdb$database') + for r in cur: + print(r[0].tzinfo) + cur.close() + + # The value set through the DPB should survive an `alter session reset` + con.execute_immediate('alter session reset') + con.commit() + + cur = con.cursor() + cur.execute('select current_timestamp from rdb$database') + for r in cur: + print(r[0].tzinfo) + + act.expected_stdout = f""" + tzfile('{SELECTED_TIMEZONE}') + tzfile('{SELECTED_TIMEZONE}') + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # .................................................................................... + + ################################################ + ### c h e c k D e c f l o a t R o u n d ### + ################################################ + # + # doc/sql.extensions/README.data_types.txt: + # CEILING (towards +infinity), + # UP (away from 0), + # HALF_UP (to nearest, if equidistant - up), + # HALF_EVEN (to nearest, if equidistant - ensure last digit in the result to be even), + # HALF_DOWN (to nearest, if equidistant - down), + # DOWN (towards 0), + # FLOOR (towards -infinity), + # REROUND (up if digit to be rounded is 0 or 5, down in other cases). + # + # Examples from functional/datatypes/test_decfloat_round_modes.py: + # + df_round_lst = ( + DecfloatRound.CEILING + ,DecfloatRound.UP + ,DecfloatRound.HALF_UP + ,DecfloatRound.HALF_EVEN + ,DecfloatRound.HALF_DOWN + ,DecfloatRound.DOWN + ,DecfloatRound.FLOOR + ,DecfloatRound.REROUND + ) + for r in df_round_lst: + db_cfg_object.decfloat_round.value = r + print(r.name) + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + + # The value set through the DPB should survive an `alter session reset` + con.execute_immediate('alter session reset') + con.commit() + + cur = con.cursor() + cur.execute('select v.* from v_test v') + ccol=cur.description + for r in cur: + for i in range(0,len(ccol)): + print( ccol[i][0],':', r[i] ) + except DatabaseError as e: + print(e.__str__()) + + # Return round option to default: + db_cfg_object.decfloat_round.value = DecfloatRound.HALF_UP + + act.expected_stdout = """ + CEILING + R1 : 12.35 + R2 : 12.35 + R3 : 12.35 + R4 : 12.36 + R5 : 12.41 + R6 : -12.34 + RX : 80.45 + RY : -80.44 + UP + R1 : 12.35 + R2 : 12.35 + R3 : 12.35 + R4 : 12.36 + R5 : 12.41 + R6 : -12.35 + RX : 80.45 + RY : -80.45 + HALF_UP + R1 : 12.34 + R2 : 12.35 + R3 : 12.35 + R4 : 12.36 + R5 : 12.41 + R6 : -12.35 + RX : 80.45 + RY : -80.45 + HALF_EVEN + R1 : 12.34 + R2 : 12.34 + R3 : 12.35 + R4 : 12.36 + R5 : 12.40 + R6 : -12.34 + RX : 80.44 + RY : -80.44 + HALF_DOWN + R1 : 12.34 + R2 : 12.34 + R3 : 12.35 + R4 : 12.35 + R5 : 12.40 + R6 : -12.34 + RX : 80.44 + RY : -80.44 + DOWN + R1 : 12.34 + R2 : 12.34 + R3 : 12.34 + R4 : 12.35 + R5 : 12.40 + R6 : -12.34 + RX : 80.44 + RY : -80.44 + FLOOR + R1 : 12.34 + R2 : 12.34 + R3 : 12.34 + R4 : 12.35 + R5 : 12.40 + R6 : -12.35 + RX : 80.44 + RY : -80.45 + REROUND + R1 : 12.34 + R2 : 12.34 + R3 : 12.34 + R4 : 12.36 + R5 : 12.41 + R6 : -12.34 + RX : 80.44 + RY : -80.44 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # .................................................................................... + + ################################################ + ### c h e c k D e c f l o a t T r a p s ### + ################################################ + # + # doc/sql.extensions/README.data_types.txt: + # SET DECFLOAT TRAPS TO + # Division_by_zero, Inexact, Invalid_operation, Overflow and Underflow + # + + # Examples from functional/datatypes/test_decfloat_exceptions_trapping.py: + # + df_traps_map = { + DecfloatTraps.DIVISION_BY_ZERO : + ( 'select 1/1e-9999' + ,'Decimal float divide by zero.' + ) + ,DecfloatTraps.INEXACT : + ( 'select 1e9999 + 1e9999' + ,'Decimal float inexact result.' + ) + ,DecfloatTraps.INVALID_OPERATION : + ( "select cast('34ffd' as decfloat(16))" + ,'Decimal float invalid operation.' + ) + ,DecfloatTraps.OVERFLOW : + ( 'select 1e9999' + ,'Decimal float overflow.' + ) + ,DecfloatTraps.UNDERFLOW : + ( 'select 1e-9999' + ,'Decimal float underflow.' + ) + } + + expected_out_lst = [] + actual_out_lst = [] + expected_iter = 'EXPECTED error message raised.' + for k,v in df_traps_map.items(): + traps_option = k + execute_sttm = v[0] + ' from rdb$database' + expected_msg = v[1] + db_cfg_object.decfloat_traps.value = [traps_option,] + + # expected_out_lst.append( str(db_cfg_object.decfloat_traps.value[0]) ) # name of option + expected_out_lst.append(traps_option.name) + expected_out_lst.append(expected_iter) + + actual_out_lst.append(traps_option.name) + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + # The value set through the DPB should survive an `alter session reset` + con.execute_immediate('alter session reset') + con.commit() + + cur = con.cursor() + cur.execute(execute_sttm) + for r in cur: + pass + except DatabaseError as e: + if expected_msg in e.__str__(): + actual_out_lst.append(expected_iter) + else: + actual_out_lst.append('UNEXPECTED ERROR MESSAGE:\n' + e.__str__()) + + + act.expected_stdout = '\n'.join(expected_out_lst) + act.stdout = '\n'.join(actual_out_lst) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # Return traps option to default: + db_cfg_object.decfloat_traps.value = [] + From 1042d0380dbd0498cd76c8796dca23fcd3ece856 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 22 Jul 2024 20:04:50 +0300 Subject: [PATCH 0089/1064] Added/Updated tests\bugs\gh_6267_test.py: Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127 --- tests/bugs/gh_6267_test.py | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/bugs/gh_6267_test.py diff --git a/tests/bugs/gh_6267_test.py b/tests/bugs/gh_6267_test.py new file mode 100644 index 00000000..e5fa01c1 --- /dev/null +++ b/tests/bugs/gh_6267_test.py @@ -0,0 +1,43 @@ +#coding:utf-8 + +""" +ID: issue-6267 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6267 +TITLE: Add transaction info fb_info_tra_snapshot_number [CORE6017] +DESCRIPTION: + Test verifies ability to use appropriate API info and whether value of + returned snapshot_number equals to RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER'). +NOTES: + [22.07.2024] pzotov + Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127 +""" + +import pytest +from firebird.qa import * +from firebird.driver import tpb, Isolation + +db = db_factory() +act = python_act('db') + +CUSTOM_TPB = tpb(isolation = Isolation.SNAPSHOT) + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + with act.db.connect() as con: + tx1 = con.transaction_manager(CUSTOM_TPB) + tx1.begin() + cur1 = tx1.cursor() + + cur1.execute("select RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER') from rdb$database") + ctx_sn = int(cur1.fetchone()[0]) + if ctx_sn == tx1.info.snapshot_number: + print('OK') + else: + print(f'MISMATCH: RDB$GET_CONTEXT={ctx_sn}, {tx1.info.snapshot_number=}') + tx1.commit() + + act.expected_stdout = """ + OK + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 045c44b0355411f8ea01ad9a2f11c3867050d4cc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 22 Jul 2024 20:36:58 +0300 Subject: [PATCH 0090/1064] Added/Updated tests\bugs\gh_6120_test.py: Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127, 3.0.12.33765 --- tests/bugs/gh_6120_test.py | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/bugs/gh_6120_test.py diff --git a/tests/bugs/gh_6120_test.py b/tests/bugs/gh_6120_test.py new file mode 100644 index 00000000..1009f6df --- /dev/null +++ b/tests/bugs/gh_6120_test.py @@ -0,0 +1,58 @@ +#coding:utf-8 + +""" +ID: issue-6120 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6120 +TITLE: Support auth_plugin_list dpb/spb item from application to client [CORE5860] +DESCRIPTION: +NOTES: + [22.07.2024] pzotov + Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127, 3.0.12.33765 +""" +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol, DatabaseError + +db = db_factory() +act = python_act('db') + +tmp_srp_user = user_factory('db', name='tmp$6120_srp', password='123', plugin = 'Srp') +tmp_leg_user = user_factory('db', name='tmp$6120_leg', password='456', plugin = 'Legacy_UserManager') + +@pytest.mark.version('>=3.0.3') +def test_1(act: Action, tmp_srp_user: User, tmp_leg_user: User, capsys): + + srv_cfg = driver_config.register_server(name = 'srv_cfg_6120', config = '') + + db_cfg_name = f'db_cfg_6120' + + # DatabaseConfig; see PYTHON_HOME/Lib/site-packages/firebird/driver/config.py: + db_cfg_object = driver_config.register_database(name = db_cfg_name) + + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.auth_plugin_list.value = ','.join( ['Srp', 'Legacy_Auth'] ) + + for u in (tmp_srp_user, tmp_leg_user): + with connect(db_cfg_name, user = u.name, password = u.password) as con: + cur = con.cursor() + try: + cur.execute('select trim(mon$user) as mon_user, mon$auth_method as auth_way from mon$attachments') + ccol=cur.description + for r in cur: + for i in range(0,len(ccol)): + print( ccol[i][0],':', r[i] ) + except DatabaseError as e: + print(e.__str__()) + + act.expected_stdout = f""" + MON_USER : TMP$6120_SRP + AUTH_WAY : Srp + + MON_USER : TMP$6120_LEG + AUTH_WAY : Legacy_Auth + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 6d9ce9f1260b9c79338dc868244b6f9f9a5c96e0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 22 Jul 2024 20:38:57 +0300 Subject: [PATCH 0091/1064] Added/Updated tests\bugs\gh_6120_test.py: minor change: added comment --- tests/bugs/gh_6120_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/bugs/gh_6120_test.py b/tests/bugs/gh_6120_test.py index 1009f6df..0299fb51 100644 --- a/tests/bugs/gh_6120_test.py +++ b/tests/bugs/gh_6120_test.py @@ -7,6 +7,9 @@ DESCRIPTION: NOTES: [22.07.2024] pzotov + Improvement appeared 28.08.2018 18:47, commit: + https://github.com/FirebirdSQL/firebird/commit/dc06a58a1a7923a5954f33c8c131ae3eaf59b907 + Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127, 3.0.12.33765 """ import pytest From bfc56f8e90f9804be38447f60bd76afe010b23c5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 23 Jul 2024 18:00:56 +0300 Subject: [PATCH 0092/1064] Added/Updated git-commit-adjust-output.bat: gh_6282_test.py See notes. To get exact string containing name of selected time zone (both on Windows and Linux), one need to use tzinfo._timezone_ --- git-commit-adjust-output.bat | 162 +++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 git-commit-adjust-output.bat diff --git a/git-commit-adjust-output.bat b/git-commit-adjust-output.bat new file mode 100644 index 00000000..1c468f18 --- /dev/null +++ b/git-commit-adjust-output.bat @@ -0,0 +1,162 @@ +@echo off +setlocal enabledelayedexpansion enableextensions + +@rem git config --global user.email "you@example.com" +@rem git config --global user.name "Your Name" +set GITCMD=C:\mix\Git\bin\git.exe + +set qa_root=%~dp0 +set file_ext=^ +set git_text=Updated "!file_ext!": adjust expected stdout/stderr to current FB version. +if .%1.==.. goto syntax + +set pytest_file=%1 + +if NOT .%2.==.. ( + set /a i=0 + @rem echo all inp arguments: ^|"%*"^| + for /f "tokens=1* delims= " %%a in ("%*") do ( + set customer_comment=%%b + ) + @rem echo customer comment: ^|!customer_comment!^| + + set git_text=Added/Updated "!file_ext!": !customer_comment! +) + +set joblog=%~dpn0.log +set tmplog=%~dpn0.tmp + +del !joblog! 2>nul +del !tmplog! 2>nul + +for /f %%a in ("!pytest_file!") do ( + @rem set file_ext=%%~nxa + set file_ext=%%a + set text_chk=!file_ext:%qa_root%=! + if .!text_chk!.==.!file_ext!. ( + @rem .fbt was specified WITHOUT path + set file_ext=%cd%\!file_ext! + ) + set file_ext=!file_ext:%qa_root%=! + +) +set git_text=!git_text:^=%file_ext%! + +( + echo Log for: %~f0 !pytest_file! + echo Created !date! !time! on host '%COMPUTERNAME%' + echo. + echo Comment is: git_text=!git_text! +) >>!joblog! + +set msg=!date! !time! Processing command: !GITCMD! add !pytest_file! +echo !msg! +echo !msg!>>!joblog! + +@rem ############################ +@rem ### g i t a d d ### +@rem ############################ +!GITCMD! add !pytest_file! 1>!tmplog! 2>&1 +set /a elevel=!errorlevel! +echo elevel=!elevel! +echo elevel=!elevel!>>!joblog! + +type !tmplog! +type !tmplog! >>!joblog! + +if !elevel! GTR 0 ( + echo ERROR OCCURED. Check log: + echo ------------------------- + type !tmplog! + echo ------------------------- + del !tmplog! + goto :final +) + +!GITCMD! status !pytest_file! 1>>!joblog! 2>&1 + +set msg=!date! !time! Processing command: !GITCMD! commit -m "!git_text!" -- !pytest_file! +echo !msg! +echo !msg!>>!joblog! + +@rem ################################## +@rem ### g i t c o m m i t ### +@rem ################################## +!GITCMD! commit -m "!git_text!" -- !pytest_file! 1>!tmplog! 2>&1 +set elevel=!errorlevel! +echo elevel=!elevel! +echo elevel=!elevel!>>!joblog! +type !tmplog! >>!joblog! +if !elevel! GTR 0 ( + echo ERROR OCCURED. Check log: + echo ------------------------- + type !tmplog! + echo ------------------------- + del !tmplog! + goto :final +) + + +set msg=!date! !time! Processing command: !GITCMD! push +echo !msg! +echo !msg!>>!joblog! + +@rem ############################## +@rem ### g i t p u s h ### +@rem ############################## +!GITCMD! push 1>!tmplog! 2>&1 +set elevel=!errorlevel! +echo elevel=!elevel! +echo elevel=!elevel!>>!joblog! +type !tmplog! >>!joblog! +if !elevel! GTR 0 ( + echo ERROR OCCURED. Check log: + echo ------------------------- + type !tmplog! + echo ------------------------- + del !tmplog! + goto :final +) + +del !tmplog! 2>nul + +echo ------ OVERALL LOG: -------- +type !joblog! +echo ---------------------------- + +set msg=!date! !time! Check result of commits here: +echo !msg! +!GITCMD! config --get remote.origin.url +( + echo !msg! + !GITCMD! config --get remote.origin.url +) >> !joblog! + +@rem ####################################### +@rem ### s e n d i n g m a i l ### +@rem ####################################### +call %~dp0qa-sendmail.bat "!git_text!" !joblog! + +@rem https://github.com/FirebirdSQL/fbt-repository.git + +goto final + +:syntax + echo. + echo Syntax: + echo 1. %~f0 ^ + echo. + echo. Commit will be done with comment: + echo. !git_text! + echo. + echo. + echo 2. %~f0 ^ some very clever comment here + echo. + echo. Commit will be done with comment: + echo. some very clever comment here + echo. + pause + goto final +:final + echo Bye-bye from %~f0 + From 50fcaea7f28b47f970859a81e8946f5cdbf7a0ae Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 24 Jul 2024 23:03:23 +0300 Subject: [PATCH 0093/1064] Added/Updated tests\bugs\gh_8176_test.py: removed pytest.skip directive for CS after check on 6.0.0.398-f59905f, 5.0.1.1440-7b1b824 --- tests/bugs/gh_8176_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_8176_test.py b/tests/bugs/gh_8176_test.py index c3abede1..484428e8 100644 --- a/tests/bugs/gh_8176_test.py +++ b/tests/bugs/gh_8176_test.py @@ -30,6 +30,16 @@ Confirmed bug on 6.0.0.389-cc71c6f (SS), 5.0.1.1432-9d5a60a (SS) - server hanged and did not allow to make new connections to test DB. Checked on 6.0.0.392-3fa8e6b, 5.0.1.1434-2593b3b. + + [24.07.2024] pzotov + Checked fixed problem with hang on Windows, Servermode = CLASSIC + Commits: + https://github.com/FirebirdSQL/firebird/commit/fa90256cf080965f92eae11eba8d897c2d02e1b9 + Merge pull request #8186 from FirebirdSQL/work/ProfilerIPC + Fixed a few issues with IPC used by remote profiler + https://github.com/FirebirdSQL/firebird/commit/f59905fc29f0b9288d61fc6113fd24301dce1327 + Frontported PR #8186 : Fixed a few issues with IPC used by remote profiler + Snapshots: 6.0.0.398-f59905f, 5.0.1.1440-7b1b824 """ import pytest @@ -101,9 +111,6 @@ @pytest.mark.version('>=5.0.1') def test_1(act: Action, tmp_worker_usr: User, tmp_profiler_usr: User, tmp_profiler_role: Role, capsys): - if act.vars['server-arch'] != 'SuperServer': - pytest.skip("SEE NOTES: currently Super only.") - addi_script = f""" set wng off; set bail on; From 48e158d158d3ceae5cad23ee781df437bc6cbefd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 29 Jul 2024 18:34:28 +0300 Subject: [PATCH 0094/1064] Added/Updated tests\bugs\gh_7057_test.py: Checked on 6.0.0.401-a7d10a4. Currently min_version=6.0.0 until backports to previous versions will appear. --- tests/bugs/gh_7057_test.py | 146 +++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 tests/bugs/gh_7057_test.py diff --git a/tests/bugs/gh_7057_test.py b/tests/bugs/gh_7057_test.py new file mode 100644 index 00000000..c943e4f6 --- /dev/null +++ b/tests/bugs/gh_7057_test.py @@ -0,0 +1,146 @@ +#coding:utf-8 + +""" +ID: issue-7057 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7057 +TITLE: Client-side positioned updates work wrongly with scrollable cursors +DESCRIPTION: + Fetching from a scrollable cursor may overwrite user-specified buffer and corrupt memory. + Engine did overwrite the user-specified buffer with four more bytes than expected that could corrupt the caller memory. + Discussed between dimitr, pcisar and pzotov, see letters of 29-30 NOV 2021, + subj: "firebird-driver & scrollable cursors // misc. tests, requested by dimitr" +NOTES: + [29.07.2024] pzotov + 1. ### ACHTUNG ### + Old snapshots (before 5.0.0.890-aa847a7) must be checked with usage "--disable-db-cache" command switch for pytest! + Otherwise one may FALSE failure (bugcheck) with: + "internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 293)" + 2. Test caused crash of server on snapshots before 6.0.0.401-a7d10a4. + Problem related to MaxStatementCacheSize which default value > 0 + (explained by dimitr, letter 19-JUL-2024 12:52). + It seems that bug was fixed in https://github.com/FirebirdSQL/firebird/commit/a7d10a40147d326e56540498b50e40b2da0e5850 + ("Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on.") + 3. Currently this test can run only in 6.0.0.401-a7d10a4 and later. + + Checked on 6.0.0.401-a7d10a4. +""" +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol, DatabaseError +import re + +db = db_factory() +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +#------------------------------------------------------ +def print_row(row, cur = None): + if row: + print(f"{row[0]}") + if cur and (cur.is_bof() or cur.is_eof()): + print('### STRANGE BOF/EOR WHILE SOME DATA CAN BE SEEN ###') + else: + msg = '*** NO_DATA***' + if cur: + msg += ' BOF=%r EOF=%r' % ( cur.is_bof(), cur.is_eof() ) + print(msg) +#------------------------------------------------------ + + +@pytest.mark.scroll_cur +@pytest.mark.version('>=6.0.0') +def test_1(act: Action, capsys): + with act.db.connect() as con: + con.execute_immediate('recreate table ts(id int)') + con.commit() + con.execute_immediate('insert into ts (id) select row_number() over() from rdb$types rows 10') + con.commit() + + cur = con.cursor() + cur.open('select id from ts for update') + cur.set_cursor_name('X') + + for row in cur: + print_row(row) + + cur.fetch_first() + print('Updating first record') + con.execute_immediate('update ts set id = -id where current of X') + con.commit() + + cur = con.cursor() + cur.open('select id from ts for update') + cur.set_cursor_name('X') + + for row in cur: + print_row(row) + + cur.fetch_last() + print('Updating last record') + con.execute_immediate('update ts set id = -id where current of X') + con.commit() + + cur = con.cursor() + cur.open('select id from ts for update') + cur.set_cursor_name('X') + + for row in cur: + print_row(row) + + cur.fetch_absolute(5) + print('Updating 5th record') + con.execute_immediate('update ts set id = -id where current of X') + con.commit() + + cur = con.cursor() + cur.open('select id from ts') + + for row in cur: + print_row(row) + + act.stdout = capsys.readouterr().out + act.expected_stdout = """ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + Updating first record + -1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + Updating last record + -1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + -10 + Updating 5th record + -1 + 2 + 3 + 4 + -5 + 6 + 7 + 8 + 9 + -10 + """ + assert act.clean_stdout == act.clean_expected_stdout From cb5a75c52862ff83cbcc10d0eb9524710be6645e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 29 Jul 2024 19:41:54 +0300 Subject: [PATCH 0095/1064] Added/Updated tests\bugs\gh_7057_test.py: Raised min_version after check on fresh 5.0.1 -- see notes. Checked on 6.0.0.401-a7d10a4, 5.0.1.1453-62ee5f1. --- tests/bugs/gh_7057_test.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_7057_test.py b/tests/bugs/gh_7057_test.py index c943e4f6..6ded37b9 100644 --- a/tests/bugs/gh_7057_test.py +++ b/tests/bugs/gh_7057_test.py @@ -18,11 +18,16 @@ 2. Test caused crash of server on snapshots before 6.0.0.401-a7d10a4. Problem related to MaxStatementCacheSize which default value > 0 (explained by dimitr, letter 19-JUL-2024 12:52). - It seems that bug was fixed in https://github.com/FirebirdSQL/firebird/commit/a7d10a40147d326e56540498b50e40b2da0e5850 - ("Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on.") - 3. Currently this test can run only in 6.0.0.401-a7d10a4 and later. + + It seems that bug was fixed in: + FB 5.x: https://github.com/FirebirdSQL/firebird/commit/08dc25f8c45342a73c786bc60571c8a5f2c8c6e3 (27.07.2024 14:55) + FB 6.x: https://github.com/FirebirdSQL/firebird/commit/a7d10a40147d326e56540498b50e40b2da0e5850 (29.07.2024 03:53) + ("Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on.") - Checked on 6.0.0.401-a7d10a4. + 3. Attempt to run this test on FB 4.0.5.3127 (10-JUL-2024) raises: + "E firebird.driver.types.DatabaseError: feature is not supported" + + Checked on 6.0.0.401-a7d10a4, 5.0.1.1453-62ee5f1. """ import pytest from firebird.qa import * @@ -47,7 +52,7 @@ def print_row(row, cur = None): @pytest.mark.scroll_cur -@pytest.mark.version('>=6.0.0') +@pytest.mark.version('>=5.0.1') def test_1(act: Action, capsys): with act.db.connect() as con: con.execute_immediate('recreate table ts(id int)') From d44c33b9e59aa0790177499e53d7e2c6f85843da Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 29 Jul 2024 19:57:03 +0300 Subject: [PATCH 0096/1064] Added/Updated tests\bugs\gh_7057_test.py: minor change - added comment --- tests/bugs/gh_7057_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_7057_test.py b/tests/bugs/gh_7057_test.py index 6ded37b9..80f1600b 100644 --- a/tests/bugs/gh_7057_test.py +++ b/tests/bugs/gh_7057_test.py @@ -26,6 +26,7 @@ 3. Attempt to run this test on FB 4.0.5.3127 (10-JUL-2024) raises: "E firebird.driver.types.DatabaseError: feature is not supported" + (scollable cursors are not supported in network protocol in FB-4.x) Checked on 6.0.0.401-a7d10a4, 5.0.1.1453-62ee5f1. """ From b9ac7029fe97de1b99d29aa03d76653260cc9a93 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 31 Jul 2024 23:14:40 +0300 Subject: [PATCH 0097/1064] Added/Updated tests\bugs\core_4964_test.py: Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout. Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/27 --- tests/bugs/core_4964_test.py | 326 ++++++++++++++++++++--------------- 1 file changed, 186 insertions(+), 140 deletions(-) diff --git a/tests/bugs/core_4964_test.py b/tests/bugs/core_4964_test.py index 69ea1246..81836d2f 100644 --- a/tests/bugs/core_4964_test.py +++ b/tests/bugs/core_4964_test.py @@ -1,140 +1,186 @@ -#coding:utf-8 - -""" -ID: issue-5255 -ISSUE: 5255 -JIRA: CORE-4964 -FBTEST: bugs.core_4964 -TITLE: Real errors during connect to security database are hidden by Srp user manager. Errors should be logged no matter what AuthServer is used -DESCRIPTION: - Test does following: - 1) creates temporary user using plugin Srp (in order to avoid occasional connect as SYSDBA using Legacy plugin); - 2) makes copy of test DB to file which is specified n databases.conf as database for alias defined by variable with name REQUIRED_ALIAS - (its value: 'tmp_4964_alias'; test will try to connect to this file via ALIAS from pre-created databases.conf); - 3) uses pre-created databases.conf which has alias and SecurityDatabase parameter in its details. - This parameter that points to existing file that for sure can NOT be a Firebird database - (file $(dir_conf)/firebird.msg is used for this purpose). - - Then we: - 1) obtain content of server firebird.log; - 2) try to make connect to alias and (as expected) get error; - 3) obtain again content of server firebird.log and compare to origin one. - -NOTES: - [02.08.2022] pzotov - 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. - 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf - (for LINUX this equality is case-sensitive, even when aliases are compared!) - 3. Make sure that firebird was launched by user who is currently runs this test. - Otherwise shutil.copy2() failes with "[Errno 13] Permission denied". - 4. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). - Discussed with pcisar, letters since 30-may-2022 13:48, subject: - "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" - - Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux. -""" - -import re -import time -from pathlib import Path -from difflib import unified_diff - -import pytest -from firebird.qa import * - -substitutions = [('[ \t]+', ' '), ('file .* is not a valid database', 'file is not a valid database'), ] - -REQUIRED_ALIAS = 'tmp_core_4964_alias' - -db = db_factory() -act = python_act('db', substitutions=substitutions) -tmp_user = user_factory('db', name='tmp$c4964', password='123', plugin = 'Srp') - -expected_stdout_isql = """ - Statement failed, SQLSTATE = 08006 - Error occurred during login, please check server firebird.log for details -""" - -expected_stdout_log_diff = """ - Authentication error - file is not a valid database -""" - -@pytest.mark.version('>=3.0') -def test_1(act: Action, tmp_user: User, capsys): - - fblog_1 = act.get_firebird_log() - - # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that - # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). - # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': - p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) - fname_in_dbconf = None - - with open(act.home_dir/'databases.conf', 'r') as f: - for line in f: - if p_required_alias_ptn.search(line): - # If databases.conf contains line like this: - # tmp_4964_alias = $(dir_sampleDb)/qa/tmp_qa_4964.fdb - # - then we extract filename: 'tmp_qa_4964.fdb' (see below): - fname_in_dbconf = Path(line.split('=')[1].strip()).name - break - - # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! - # - assert fname_in_dbconf - - # Full path + filename of database to which we will try to connect: - # - tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) - - # PermissionError: [Errno 13] Permission denied --> probably because - # Firebird was started by root rather than current (non-privileged) user. - # - tmp_fdb.write_bytes(act.db.db_path.read_bytes()) - - check_sql = f''' - set bail on; - set list on; - connect '{act.host+":" if act.host else ""}{tmp_fdb}' user {tmp_user.name} password {tmp_user.password}; - -- This can occus only if we databases.conf contains {REQUIRED_ALIAS} - -- but without reference to invalid security DB (e.g., alias without curly braces at all): - select mon$database_name as "UNEXPECTED CONNECTION:" from mon$database; - quit; - ''' - - ############################################################################################################### - # POINT-1: check that ISQL raises: - # "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log ..." - # - act.expected_stdout = expected_stdout_isql - try: - act.isql(switches = ['-q'], input = check_sql, connect_db=False, credentials = False, combine_output = True) - finally: - tmp_fdb.unlink() - - assert act.clean_stdout == act.clean_expected_stdout - act.reset() - - time.sleep(1) # Allow content of firebird log be fully flushed on disk. - fblog_2 = act.get_firebird_log() - - diff_patterns = [ - "\\+\\s+Authentication error", - "\\+\\s+file .* is not a valid database", - ] - diff_patterns = [re.compile(s) for s in diff_patterns] - - for line in unified_diff(fblog_1, fblog_2): - if line.startswith('+'): - if act.match_any(line, diff_patterns): - print(line.split('+')[-1]) - - ############################################################################################################### - # POINT-2: check that diff between firebird.log initial and current content has phrases - # 'Authentication error' and '... file is not a valid database': - # - act.expected_stdout = expected_stdout_log_diff - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - act.reset() +#coding:utf-8 + +""" +ID: issue-5255 +ISSUE: 5255 +JIRA: CORE-4964 +FBTEST: bugs.core_4964 +TITLE: Real errors during connect to security database are hidden by Srp user manager. Errors should be logged no matter what AuthServer is used +DESCRIPTION: + Test does following: + 1) creates temporary user using plugin Srp (in order to avoid occasional connect as SYSDBA using Legacy plugin); + 2) makes copy of test DB to file which is specified n databases.conf as database for alias defined by variable with name REQUIRED_ALIAS + (its value: 'tmp_4964_alias'; test will try to connect to this file via ALIAS from pre-created databases.conf); + 3) uses pre-created databases.conf which has alias and SecurityDatabase parameter in its details. + This parameter that points to existing file that for sure can NOT be a Firebird database + (file $(dir_conf)/firebird.msg is used for this purpose). + + Then we: + 1) obtain content of server firebird.log; + 2) try to make connect to alias and (as expected) get error; + 3) obtain again content of server firebird.log and compare to origin one. + +NOTES: + [02.08.2022] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + 3. Make sure that firebird was launched by user who is currently runs this test. + Otherwise shutil.copy2() failes with "[Errno 13] Permission denied". + 4. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + + [31.07.2024] pzotov + Replaced assert for ISQL output: added diff_patterns that must filter STDERR because we have to suppress message with text + "file ... is not a valid database" as it can be seen only in dev-builds. + Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout + Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/27 + + Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux. +""" + +import re +import time +from pathlib import Path +from difflib import unified_diff + +import pytest +from firebird.qa import * + +substitutions = [ + ('[ \t]+', ' ') + ,('(-)?file .* is not a valid database', 'file is not a valid database') + ] + +REQUIRED_ALIAS = 'tmp_core_4964_alias' + +db = db_factory() +act = python_act('db', substitutions = substitutions) +tmp_user = user_factory('db', name='tmp$c4964', password='123', plugin = 'Srp') + +expected_stdout_isql = """ + Statement failed, SQLSTATE = 08006 + Error occurred during login, please check server firebird.log for details +""" + +expected_stdout_log_diff = """ + Authentication error + file is not a valid database +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User, capsys): + + fblog_1 = act.get_firebird_log() + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_4964_alias = $(dir_sampleDb)/qa/tmp_qa_4964.fdb + # - then we extract filename: 'tmp_qa_4964.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + # Full path + filename of database to which we will try to connect: + # + tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) + + # PermissionError: [Errno 13] Permission denied --> probably because + # Firebird was started by root rather than current (non-privileged) user. + # + tmp_fdb.write_bytes(act.db.db_path.read_bytes()) + + check_sql = f''' + set bail on; + set list on; + connect '{act.host+":" if act.host else ""}{tmp_fdb}' user {tmp_user.name} password {tmp_user.password}; + -- This can occus only if we databases.conf contains {REQUIRED_ALIAS} + -- but without reference to invalid security DB (e.g., alias without curly braces at all): + select mon$database_name as "UNEXPECTED CONNECTION:" from mon$database; + quit; + ''' + + ############################################################################################################### + # POINT-1: check that ISQL raises: + # "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log ..." + # + + # release build: + # ================================== + # Statement failed, SQLSTATE = 08006 + # Error occurred during login, please check server firebird.log for details + # ================================== + + # dev-build: + # ================================== + # Statement failed, SQLSTATE = 08006 + # Error occurred during login, please check server firebird.log for details + # -file ... is not a valid database + # ================================== + # Last line ("file ... is not a valid database") will be suppressed by substitutions set: + # + + isql_err_diff_patterns = [ + "Statement failed, SQLSTATE = 08006" + ,"Error occurred during login, please check server firebird.log for details" + ] + isql_err_diff_patterns = [re.compile(s) for s in isql_err_diff_patterns] + + act.expected_stdout = expected_stdout_isql + try: + act.isql(switches = ['-q'], input = check_sql, connect_db=False, credentials = False, combine_output = True) + finally: + tmp_fdb.unlink() + + # ::: NB ::: + # Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout + for line in act.stdout.splitlines(): + if act.match_any(line, isql_err_diff_patterns): + print(line) + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + time.sleep(1) # Allow content of firebird log be fully flushed on disk. + fblog_2 = act.get_firebird_log() + + fb_log_diff_patterns = [ + "\\+\\s+Authentication error" + ,"\\+\\s+file .* is not a valid database" + ] + fb_log_diff_patterns = [re.compile(s) for s in fb_log_diff_patterns] + + # BOTH release and dev build will print in firebird.log: + # + # Authentication error + # file .* is not a valid database + # + for line in unified_diff(fblog_1, fblog_2): + if line.startswith('+'): + if act.match_any(line, fb_log_diff_patterns): + print(line.split('+')[-1]) + + ############################################################################################################### + # POINT-2: check that diff between firebird.log initial and current content has phrases + # 'Authentication error' and '... file is not a valid database': + # + act.expected_stdout = expected_stdout_log_diff + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + From a3a170d07c5f8b0424af6d39322f52240b3e59c6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 1 Aug 2024 20:31:57 +0300 Subject: [PATCH 0098/1064] Added/Updated tests\bugs\core_5691_test.py: re.sub() calls must be applied to every obtained binary file description because it my contain `(NN-bit debug)` suffix if we run test against dev-build. --- tests/bugs/core_5691_test.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_5691_test.py b/tests/bugs/core_5691_test.py index b3b255d1..c3c71ed9 100644 --- a/tests/bugs/core_5691_test.py +++ b/tests/bugs/core_5691_test.py @@ -22,8 +22,17 @@ [28.03.2024] pzotov Removed loop with search for 'file description' attribute because it is useless in case when system locale differs from English (e.g. russian etc). Defined constant with value = 34. + + [01.08.2024] pzotov + re.sub() calls must be applied to every obtained binary file description because it my contain "(NN-bit debug)" + suffix if we run test against dev-build, e.g.: + 'fbclient.dll' : firebird client library (64-bit debug) + We have to remove such suffix (together with "NN-bit" and parenthesis). + Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/29 """ + import os +import re from pathlib import Path import subprocess import time @@ -158,10 +167,11 @@ def test_1(act: Action, tmp_vbs: Path, tmp_log: Path, capsys): for x in sorted(f_list): subprocess.call( [ 'cscript', '//nologo', str(tmp_vbs), act.vars['bin-dir'] / x ], stdout = vbs_log, stderr = subprocess.STDOUT) - + # 'fbclient.dll' : firebird client library (64-bit debug) with open( tmp_log,'r') as f: for line in f: - print( line.lower() ) + # 01.08.2024: added 're.sub()' here, see notes: + print( re.sub(r'\s+\(\d+(\s+|-)bit debug\)', '', line.lower()) ) expected_stdout = f""" 'fb_lock_print.exe' : firebird lock print tool From 9c70256e5674cb8d91e299fc08e5bef14c72abe7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 2 Aug 2024 11:36:32 +0300 Subject: [PATCH 0099/1064] Added/Updated tests\bugs\core_6469_test.py: One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov). ISQL output must be checked for matching to expected before trace log (see func run_script()). Replaced hard-coded name of role with 'f{tmp_role.name}' notation. --- tests/bugs/core_6469_test.py | 594 ++++++++++++++++++----------------- 1 file changed, 311 insertions(+), 283 deletions(-) diff --git a/tests/bugs/core_6469_test.py b/tests/bugs/core_6469_test.py index 20d75618..357dfb37 100644 --- a/tests/bugs/core_6469_test.py +++ b/tests/bugs/core_6469_test.py @@ -1,283 +1,311 @@ -#coding:utf-8 - -""" -ID: issue-2376 -ISSUE: 2376 -TITLE: Provide ability to see in the trace log actions related to session management (e.g. ALTER SESSION RESET) -DESCRIPTION: - Test verifies management statements which are specified in doc/sql.extensions/README.management_statements_psql.md - We launch trace session before ISQL and stop it after its finish. - Every management statement is expected to be found in the trace log. - - ATTENTION: TWO SEPARATE BRANCHES present in this test for different OS. - - NOTES FOR WINDOWS - ################# - Statement 'SET TRUSTED ROLE' is verified for appearance in the trace log. - There are several prerequisites that must be met for check SET TRUSTED ROLE statement: - * BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place; - * current OS user has admin rights; - * OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET); - * Two mappings are created (both uses plugin win_sspi): - ** from any user to user; - ** from predefined_group domain_any_rid_admins to role - - Connect to database should be done in form: CONNECT ':' role ', - and after this we can user 'SET TRUSTED ROLE' statement (see also: core_5887-trusted_role.fbt). - - ::: NOTE ::: - We have to remove OS-veriable 'ISC_USER' before any check of trusted role. - This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) - - NOTES FOR LINUX - ############### - Trusted role is not verified for this case. - Weird behaviour detected when test was ran on FB 4.0.0.2377 SuperServer: if we run this test several times (e.g. in loop) then *all* - statements related to session management can be missed in the trace - despite the fact that they *for sure* was performed successfully - (this can be seen in ISQL log). It seems that fail somehow related to the duration of DELAY between subsequent runs: if delay more than ~30s - then almost no fails. But if delay is small then test can fail for almost every run. - NO such trouble in the Classic. - The reason currently (03-mar-2021) remains unknown. - Sent letter to Alex et al, 03-mar-2021. -NOTES: -[09.02.2022] pcisar - Test fails on Windows as script execution fails with: - Statement failed, SQLSTATE = 0P000 - Your attachment has no trusted role - -[08.04.2022] pzotov - [WINDOWS] - 1. The 'CONNECT ...' operator, being specified without USER/PASSWORD clauses, will take in account parameters that were specified in the command line - of ISQL (confirmed by Alex, letter 03.04.2022 20:31). - This means that it will use 'SYSDBA' / 'masterkey' rather than Windows trusted auth. This, in turn, leads that SYSDBA will be current user - when following is performed: - connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role tmp$r6469; - - and it causes 'set trusted role' to fail (SQLSTATE = 0P000 / Your attachment has no trusted role). - Because of this, we have to launch ISQL without using current credentials (which is True by default) - see 'credentials = False'. - 2. One need to run ISQL with requirement do NOT establish connection to the test database because this will be done in the test script itself. - Otherwise we get 'Missing security context' *after* test finishes (the reason is unknown; instead, "Rolling back work." must be issued and redirected to STDERR). - To prevent such error, we have to specify 'connect_db = False' in db_factory() call. - - Checked on 4.0.1 Release, 5.0.0.467. - - -JIRA: CORE-6469 -FBTEST: bugs.core_6469 -""" - -import os -import pytest -import re -import socket -import getpass -from pathlib import Path -from firebird.qa import * -import time - -try: - del os.environ["ISC_USER"] -except KeyError as e: - pass - -db = db_factory() - -act = python_act('db') - -test_role = role_factory('db', name='TMP$R6469') -tmp_file = temp_file('c6469_tmp.sql') - -################################ -### W I N D O W S ### -################################ - -# version: 4.0 - Windows - -expected_stdout_win = """ - alter session reset - set session idle timeout 1800 second - set statement timeout 190 second - set bind of decfloat to double precision - set decfloat round ceiling - set decfloat traps to division_by_zero - set time zone 'america/sao_paulo' - set role tmp$r6469 - set trusted role -""" - -trace_win = ['log_initfini = false', - 'log_statement_finish = true', - 'log_errors = true', - 'time_threshold = 0', - ] - -patterns_win = [re.compile('alter session reset', re.IGNORECASE), - re.compile('set session idle timeout', re.IGNORECASE), - re.compile('set statement timeout', re.IGNORECASE), - re.compile('set bind of decfloat to double precision', re.IGNORECASE), - re.compile('set decfloat round ceiling', re.IGNORECASE), - re.compile('set decfloat traps to Division_by_zero', re.IGNORECASE), - re.compile('set time zone', re.IGNORECASE), - re.compile('set role', re.IGNORECASE), - re.compile('set trusted role', re.IGNORECASE)] - -def run_script(act: Action, tmp_file: Path): - #__tracebackhide__ = True - THIS_COMPUTER_NAME = socket.gethostname() - CURRENT_WIN_ADMIN = getpass.getuser() - script = f""" - set bail on; - set list on; - set echo on; - connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; - grant tmp$r6469 to "{THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN}"; - commit; - - -- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get - -- Statement failed, SQLSTATE = 28000 /Missing security context for C:\\FBTESTING\\QA\\MISC\\C5887.FDB - -- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB: - create or alter mapping trusted_auth using plugin win_sspi from any user to user; - - -- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get - -- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role - create or alter mapping win_admins using plugin win_sspi from predefined_group domain_any_rid_admins to role tmp$r6469; - commit; - - -- We have to GRANT ROLE, even to SYSDBA. Otherwise: - -- Statement failed, SQLSTATE = 0P000 - -- Role TMP$R6469 is invalid or unavailable - grant TMP$R6469 to sysdba; - commit; - show role; - show grants; - show mapping; - - set autoddl off; - commit; - - -- Following management statements are taken from - -- doc/sql.extensions/README.management_statements_psql.md: - -- ######################################################## - alter session reset; - set session idle timeout 1800 second; - set statement timeout 190 second; - set bind of decfloat to double precision; - set decfloat round ceiling; - set decfloat traps to Division_by_zero; - set time zone 'America/Sao_Paulo'; - set role tmp$r6469; - commit; - - connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role tmp$r6469; - - select mon$user,mon$role,mon$auth_method from mon$attachments where mon$attachment_id = current_connection; - commit; - - set trusted role; - commit; - - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - drop mapping trusted_auth; - drop mapping win_admins; - commit; - """ - tmp_file.write_text(script) - - act.isql(switches=['-n', '-q'], input_file = tmp_file, connect_db = False, credentials = False) - -@pytest.mark.trace -@pytest.mark.version('>=4.0') -@pytest.mark.platform('Windows') -def test_1(act: Action, test_role: Role, tmp_file: Path, capsys): - with act.trace(db_events=trace_win): - run_script(act, tmp_file) - - # process trace - for line in act.trace_log: - if line.split(): - if act.match_any(line, patterns_win): - print(' '.join(line.split()).lower()) - # Check - act.expected_stdout = expected_stdout_win - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - - - -################################ -### L I N U X ### -################################ -# version: 4.0 - Linux - -expected_stdout_lin = """ - alter session reset - set session idle timeout 1800 second - set statement timeout 190 second - set bind of decfloat to double precision - set decfloat round ceiling - set decfloat traps to division_by_zero - set time zone 'america/sao_paulo' - set role tmp$r6469 -""" - -test_script_lin = """ - set bail on; - set list on; - - -- We have to GRANT ROLE, even to SYSDBA. Otherwise: - -- Statement failed, SQLSTATE = 0P000 - -- Role TMP$R6469 is invalid or unavailable - grant TMP$R6469 to sysdba; - commit; - - select current_user as who_ami, current_role as whats_my_role from rdb$database; - set autoddl off; - commit; - - -- Following management statements are taken from - -- doc/sql.extensions/README.management_statements_psql.md: - -- ######################################################## - set echo on; - alter session reset; - set session idle timeout 1800 second; - set statement timeout 190 second; - set bind of decfloat to double precision; - set decfloat round ceiling; - set decfloat traps to Division_by_zero; - set time zone 'America/Sao_Paulo'; - set role tmp$r6469; - commit; - select 'Completed' as msg from rdb$database; -""" - -trace_lin = ['log_initfini = false', - 'log_connections = true', - 'log_statement_finish = true', - 'log_errors = true', - 'time_threshold = 0', - ] - -patterns_lin = [re.compile('alter session reset', re.IGNORECASE), - re.compile('set session idle timeout', re.IGNORECASE), - re.compile('set statement timeout', re.IGNORECASE), - re.compile('set bind of decfloat to double precision', re.IGNORECASE), - re.compile('set decfloat round ceiling', re.IGNORECASE), - re.compile('set decfloat traps to Division_by_zero', re.IGNORECASE), - re.compile('set time zone', re.IGNORECASE), - re.compile('set role', re.IGNORECASE)] - -@pytest.mark.version('>=4.0') -@pytest.mark.platform('Linux') -def test_2(act: Action, test_role: Role, capsys): - with act.trace(db_events=trace_lin): - act.isql(switches=['-n', '-q'], input = test_script_lin) - - # process trace - for line in act.trace_log: - if line.split(): - if act.match_any(line, patterns_lin): - print(' '.join(line.split()).lower()) - # Check - act.expected_stdout = expected_stdout_lin - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - +#coding:utf-8 + +""" +ID: issue-2376 +ISSUE: 2376 +TITLE: Provide ability to see in the trace log actions related to session management (e.g. ALTER SESSION RESET) +DESCRIPTION: + Test verifies management statements which are specified in doc/sql.extensions/README.management_statements_psql.md + We launch trace session before ISQL and stop it after its finish. + Every management statement is expected to be found in the trace log. +NOTES: + [08.04.2022] pzotov + ATTENTION: TWO SEPARATE BRANCHES present in this test for different OS. + 1. NOTES FOR WINDOWS + #################### + Statement 'SET TRUSTED ROLE' is verified for appearance in the trace log. + There are several prerequisites that must be met for check SET TRUSTED ROLE statement: + * BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place; + * current OS user has admin rights, otherwise we get "SQLSTATE = 0P000 / Your attachment has no trusted role" + * OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET); + * Two mappings are created (both uses plugin win_sspi): + ** from any user to user; + ** from predefined_group domain_any_rid_admins to role + + Connect to database should be done in form: CONNECT ':' role ', + and after this we can user 'SET TRUSTED ROLE' statement (see also: core_5887-trusted_role.fbt). + + ::: NOTE ::: + We have to remove OS-veriable 'ISC_USER' before any check of trusted role. + This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from ) + + 2. NOTES FOR LINUX + ################## + Trusted role is not verified for this case. + Weird behaviour detected when test was ran on FB 4.0.0.2377 SuperServer: if we run this test several times (e.g. in loop) then *all* + statements related to session management can be missed in the trace - despite the fact that they *for sure* was performed successfully + (this can be seen in ISQL log). It seems that fail somehow related to the duration of DELAY between subsequent runs: if delay more than ~30s + then almost no fails. But if delay is small then test can fail for almost every run. + NO such trouble in the Classic. + The reason currently (03-mar-2021) remains unknown. + Sent letter to Alex et al, 03-mar-2021. + + [WINDOWS] + 1. The 'CONNECT ...' operator, being specified without USER/PASSWORD clauses, will take in account parameters that were specified in the command line + of ISQL (confirmed by Alex, letter 03.04.2022 20:31). + This means that it will use 'SYSDBA' / 'masterkey' rather than Windows trusted auth. This, in turn, leads that SYSDBA will be current user + when following is performed: + connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role tmp$r6469; + - and it causes 'set trusted role' to fail (SQLSTATE = 0P000 / Your attachment has no trusted role). + Because of this, we have to launch ISQL without using current credentials (which is True by default) - see 'credentials = False'. + 2. One need to run ISQL with requirement do NOT establish connection to the test database because this will be done in the test script itself. + Otherwise we get 'Missing security context' *after* test finishes (the reason is unknown; instead, "Rolling back work." must be issued and redirected to STDERR). + To prevent such error, we have to specify 'connect_db = False' in db_factory() call. + Checked on 4.0.1 Release, 5.0.0.467. + + [02.08.2024] pzotov + One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov). + ISQL output must be checked for matching to expected before trace log (see func run_script()). + Replaced hard-coded name of role with 'f{tmp_role.name}' notation. + + Checked on Windows 6.0.0.406, 5.0.1.1469, 4.0.5.3139 + +JIRA: CORE-6469 +FBTEST: bugs.core_6469 +""" + +import os +import ctypes +import pytest +import re +import socket +import getpass +from pathlib import Path +from firebird.qa import * +import time + +try: + del os.environ["ISC_USER"] +except KeyError as e: + pass + +db = db_factory() + +act = python_act('db') + +tmp_role = role_factory('db', name='TMP$R6469') +tmp_file = temp_file('c6469_tmp.sql') + +################################ +### W I N D O W S ### +################################ + +# version: 4.0 - Windows + +trace_win = ['log_initfini = false', + 'log_statement_finish = true', + 'log_errors = true', + 'time_threshold = 0', + ] + +patterns_win = [re.compile('alter session reset', re.IGNORECASE), + re.compile('set session idle timeout', re.IGNORECASE), + re.compile('set statement timeout', re.IGNORECASE), + re.compile('set bind of decfloat to double precision', re.IGNORECASE), + re.compile('set decfloat round ceiling', re.IGNORECASE), + re.compile('set decfloat traps to Division_by_zero', re.IGNORECASE), + re.compile('set time zone', re.IGNORECASE), + re.compile('set role', re.IGNORECASE), + re.compile('set trusted role', re.IGNORECASE)] + +#---------------------------------------------------------- + +def is_admin(): + # https://serverfault.com/questions/29659/crossplatform-way-to-check-admin-rights-in-python-script + # Checked on Windows 10. + try: + is_admin = os.getuid() == 0 + except AttributeError: + is_admin = ctypes.windll.shell32.IsUserAnAdmin() + + return is_admin + +#---------------------------------------------------------- + +def run_script(act: Action, tmp_role: Role, tmp_file: Path): + #__tracebackhide__ = True + THIS_COMPUTER_NAME = socket.gethostname() + CURRENT_WIN_ADMIN = getpass.getuser() + script = f""" + set bail on; + set list on; + -- set echo on; + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + grant {tmp_role.name} to "{THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN}"; + commit; + + -- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get + -- Statement failed, SQLSTATE = 28000 /Missing security context for C:\\FBTESTING\\QA\\MISC\\C5887.FDB + -- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB: + create or alter mapping trusted_auth using plugin win_sspi from any user to user; + + -- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get + -- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role + create or alter mapping win_admins using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role.name}; + commit; + + -- We have to GRANT ROLE, even to SYSDBA. Otherwise: + -- Statement failed, SQLSTATE = 0P000 + -- Role ... is invalid or unavailable + grant {tmp_role.name} to sysdba; + commit; + --show role; + --show grants; + --show mapping; + + set autoddl off; + commit; + + -- Following management statements are taken from + -- doc/sql.extensions/README.management_statements_psql.md: + -- ######################################################## + alter session reset; + set session idle timeout 1800 second; + set statement timeout 190 second; + set bind of decfloat to double precision; + set decfloat round ceiling; + set decfloat traps to Division_by_zero; + set time zone 'America/Sao_Paulo'; + set role {tmp_role.name}; + commit; + + connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role.name}; + + select mon$user,mon$role,mon$auth_method from mon$attachments where mon$attachment_id = current_connection; + commit; + + set trusted role; + commit; + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + drop mapping trusted_auth; + drop mapping win_admins; + commit; + """ + tmp_file.write_text(script) + + act.expected_stdout = f""" + MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} + MON$ROLE {tmp_role.name.upper()} + MON$AUTH_METHOD Mapped from Win_Sspi + """ + act.isql(switches=['-n', '-q'], input_file = tmp_file, connect_db = False, credentials = False, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + +#---------------------------------------------------------- + +@pytest.mark.trace +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +def test_1(act: Action, tmp_role: Role, tmp_file: Path, capsys): + + if not is_admin(): + pytest.skip("Current OS user must have admin rights.") + + with act.trace(db_events=trace_win): + run_script(act, tmp_role, tmp_file) + + # process trace + for line in act.trace_log: + if line.split(): + if act.match_any(line, patterns_win): + print(' '.join(line.split()).lower()) + + expected_stdout_win = f""" + alter session reset + set session idle timeout 1800 second + set statement timeout 190 second + set bind of decfloat to double precision + set decfloat round ceiling + set decfloat traps to division_by_zero + set time zone 'america/sao_paulo' + set role {tmp_role.name.lower()} + set trusted role + """ + + act.expected_stdout = expected_stdout_win + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + + + +################################ +### L I N U X ### +################################ +# version: 4.0 - Linux + +trace_lin = ['log_initfini = false', + 'log_connections = true', + 'log_statement_finish = true', + 'log_errors = true', + 'time_threshold = 0', + ] + +patterns_lin = [re.compile('alter session reset', re.IGNORECASE), + re.compile('set session idle timeout', re.IGNORECASE), + re.compile('set statement timeout', re.IGNORECASE), + re.compile('set bind of decfloat to double precision', re.IGNORECASE), + re.compile('set decfloat round ceiling', re.IGNORECASE), + re.compile('set decfloat traps to Division_by_zero', re.IGNORECASE), + re.compile('set time zone', re.IGNORECASE), + re.compile('set role', re.IGNORECASE)] + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Linux') +def test_2(act: Action, tmp_role: Role, capsys): + + expected_stdout_nix = f""" + alter session reset + set session idle timeout 1800 second + set statement timeout 190 second + set bind of decfloat to double precision + set decfloat round ceiling + set decfloat traps to division_by_zero + set time zone 'america/sao_paulo' + set role {tmp_role.name.lower()} + """ + + test_script_nix = f""" + set bail on; + set list on; + + -- We have to GRANT ROLE, even to SYSDBA. Otherwise: + -- Statement failed, SQLSTATE = 0P000 + -- Role ... is invalid or unavailable + grant {tmp_role.name} to sysdba; + commit; + + select current_user as who_ami, current_role as whats_my_role from rdb$database; + set autoddl off; + commit; + + -- Following management statements are taken from + -- doc/sql.extensions/README.management_statements_psql.md: + -- ######################################################## + set echo on; + alter session reset; + set session idle timeout 1800 second; + set statement timeout 190 second; + set bind of decfloat to double precision; + set decfloat round ceiling; + set decfloat traps to Division_by_zero; + set time zone 'America/Sao_Paulo'; + set role {tmp_role.name}; + commit; + select 'Completed' as msg from rdb$database; + """ + + with act.trace(db_events=trace_lin): + act.isql(switches=['-n', '-q'], input = test_script_nix) + + # process trace + for line in act.trace_log: + if line.split(): + if act.match_any(line, patterns_lin): + print(' '.join(line.split()).lower()) + # Check + act.expected_stdout = expected_stdout_nix + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From 3f3b17286689524cb270a937e9631770f755e0a4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 2 Aug 2024 12:04:17 +0300 Subject: [PATCH 0100/1064] Added/Updated tests\bugs\core_5887_trusted_role_test.py: One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov). --- tests/bugs/core_5887_trusted_role_test.py | 331 ++++++++++++---------- 1 file changed, 180 insertions(+), 151 deletions(-) diff --git a/tests/bugs/core_5887_trusted_role_test.py b/tests/bugs/core_5887_trusted_role_test.py index 2b375ab1..d9e30601 100644 --- a/tests/bugs/core_5887_trusted_role_test.py +++ b/tests/bugs/core_5887_trusted_role_test.py @@ -1,151 +1,180 @@ -#coding:utf-8 - -""" -ID: issue-6145-B -ISSUE: 6145 -TITLE: Allow the use of management statements in PSQL blocks -DESCRIPTION: - Role can be set as TRUSTED when following conditions are true: - * BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place; - * current OS user has admin rights; - * OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET); - * Two mappings are created (both uses plugin win_sspi): - ** from any user to user; - ** from predefined_group domain_any_rid_admins to role - - Connect to database should be done in form: CONNECT ':' role ', - and after this we can user 'SET TRUSTED ROLE' statement. - - This test checks that statement 'SET TRUSTED ROLE' can be used within PSQL block rather than as DSQL. -JIRA: CORE-5887 -FBTEST: bugs.core_5887_trusted_role -NOTES: - [15.08.2022] pzotov - Checked on 5.0.0.623, 4.0.1.2692. - [04.03.2023] pzotov - Computer name must be converted to UPPERCASE, otherwise test fails. -""" - -import os -import socket -import getpass - -import pytest -from firebird.qa import * - -for v in ('ISC_USER','ISC_PASSWORD'): - try: - del os.environ[ v ] - except KeyError as e: - pass - -THIS_COMPUTER_NAME = socket.gethostname().upper() -CURRENT_WIN_ADMIN = getpass.getuser() - -db = db_factory() -act = python_act('db', substitutions=[('\t+', ' '), ('TCPv(4|6)', 'TCP')]) - -tmp_role_senior = role_factory('db', name='tmp_role_5887_senior') -tmp_role_junior = role_factory('db', name='tmp_role_5887_junior') - -@pytest.mark.version('>=4.0') -@pytest.mark.platform('Windows') -def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys): - - sql_init = f""" - create table test(id int); - grant select on test to role {tmp_role_senior.name}; - commit; - - -- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get - -- Statement failed, SQLSTATE = 28000 /Missing security context for - -- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB: - create or alter mapping trusted_auth using plugin win_sspi from any user to user; - - -- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get - -- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role - - create or alter mapping win_admins1 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_junior.name}; - commit; - create view v_info as - select a.mon$user, a.mon$role, a.mon$remote_protocol, a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection - ; - grant select on v_info to public; - commit; - """ - act.isql(switches=['-q'], input = sql_init) - assert act.clean_stdout == '' - act.reset() - - sql_check = f""" - -- This will make connection with tole = {tmp_role_junior.name} - connect '{THIS_COMPUTER_NAME}:{act.db.db_path}'; - - set list on; - select 'point-1' as msg, v.* from v_info v; - - -- MUST FAIL because neither user nor its role has no access rights to the 'TEST' table: - select count(*) as test_rows from test; - commit; - - -- Make temporary connection as SYSDBA and change mapping from predefined_group domain_any_rid_admins - -- so that any connection can get {tmp_role_senior.name} role as trusted role: - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - - drop mapping win_admins1; - grant {tmp_role_junior.name} to public; - - -- Following statement means that any attachment will be granted with role - -- which, in turn was granted for SELECT from table 'test': - create or alter mapping win_admins2 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_senior.name}; - commit; - - connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role_junior.name.upper()}; - - select 'point-2' as msg, v.* from v_info v; - - set term ^; - execute block as - begin - -- Following statement: - -- 1) must pass without any error; - -- 2) leads to change effective role from {tmp_role_junior.name} to {tmp_role_senior.name}: - set trusted role; - end - ^ - set term ;^ - commit; - - select 'point-3' as msg, v.* from v_info v; - -- this MUST PASS because of trusted role {tmp_role_senior.name} whic has needed access rights: - select count(*) as test_rows from test; - commit; - """ - - expected_out = f""" - MSG point-1 - MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} - MON$ROLE {tmp_role_junior.name.upper()} - MON$REMOTE_PROTOCOL TCP - MON$AUTH_METHOD Mapped from Win_Sspi - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} - - MSG point-2 - MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} - MON$ROLE {tmp_role_junior.name.upper()} - MON$REMOTE_PROTOCOL TCP - MON$AUTH_METHOD Mapped from Win_Sspi - - MSG point-3 - MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} - MON$ROLE {tmp_role_senior.name.upper()} - MON$REMOTE_PROTOCOL TCP - MON$AUTH_METHOD Mapped from Win_Sspi - TEST_ROWS 0 - """ - - act.expected_stdout = expected_out - act.isql(switches=['-q'], input = sql_check, connect_db=False, credentials = False, combine_output = True) - assert act.clean_stdout == act.clean_expected_stdout +#coding:utf-8 + +""" +ID: issue-6145-B +ISSUE: 6145 +TITLE: Allow the use of management statements in PSQL blocks +DESCRIPTION: + Role can be set as TRUSTED when following conditions are true: + * BOTH AuthServer and AuthClient parameters from firebird.conf contain 'Win_Sspi' as plugin, in any place; + * current OS user has admin rights; + * OS environment has *no* variables ISC_USER and ISC_PASSWORD (i.e. they must be UNSET); + * Two mappings are created (both uses plugin win_sspi): + ** from any user to user; + ** from predefined_group domain_any_rid_admins to role + + Connect to database should be done in form: CONNECT ':' role ', + and after this we can user 'SET TRUSTED ROLE' statement. + + This test checks that statement 'SET TRUSTED ROLE' can be used within PSQL block rather than as DSQL. +JIRA: CORE-5887 +FBTEST: bugs.core_5887_trusted_role +NOTES: + [15.08.2022] pzotov + Checked on 5.0.0.623, 4.0.1.2692. + [04.03.2023] pzotov + Computer name must be converted to UPPERCASE, otherwise test fails. + [02.08.2024] pzotov + One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov). + Checked on Windows 6.0.0.406, 5.0.1.1469, 4.0.5.3139 +""" + +import os +import ctypes +import socket +import getpass + +import pytest +from firebird.qa import * + +for v in ('ISC_USER','ISC_PASSWORD'): + try: + del os.environ[ v ] + except KeyError as e: + pass + +THIS_COMPUTER_NAME = socket.gethostname().upper() +CURRENT_WIN_ADMIN = getpass.getuser() + +db = db_factory() +act = python_act('db', substitutions=[('\t+', ' '), ('TCPv(4|6)', 'TCP')]) + +tmp_role_senior = role_factory('db', name='tmp_role_5887_senior') +tmp_role_junior = role_factory('db', name='tmp_role_5887_junior') + +#---------------------------------------------------------- + +def is_admin(): + # https://serverfault.com/questions/29659/crossplatform-way-to-check-admin-rights-in-python-script + # Checked on Windows 10. + try: + is_admin = os.getuid() == 0 + except AttributeError: + is_admin = ctypes.windll.shell32.IsUserAnAdmin() + + return is_admin + +#---------------------------------------------------------- + +@pytest.mark.version('>=4.0') +@pytest.mark.platform('Windows') +def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys): + + if not is_admin(): + pytest.skip("Current OS user must have admin rights.") + + sql_init = f""" + set bail on; + create table test(id int); + grant select on test to role {tmp_role_senior.name}; + commit; + + -- We have to use here "create mapping trusted_auth ... from any user to user" otherwise get + -- Statement failed, SQLSTATE = 28000 /Missing security context for + -- on connect statement which specifies COMPUTERNAME:USERNAME instead path to DB: + create or alter mapping trusted_auth using plugin win_sspi from any user to user; + commit; + -- We have to use here "create mapping win_admins ... DOMAIN_ANY_RID_ADMINS" otherwise get + -- Statement failed, SQLSTATE = 0P000 / Your attachment has no trusted role + + create or alter mapping win_admins1 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_junior.name}; + + create view v_info as + select a.mon$user, a.mon$role, a.mon$remote_protocol, a.mon$auth_method from mon$attachments a where mon$attachment_id = current_connection + ; + grant select on v_info to public; + commit; + """ + + act.isql(switches=['-q'], input = sql_init, combine_output = True) + assert act.clean_stdout == '' + act.reset() + + sql_check = f""" + -- DO NOT add 'set bail' here! + -- This will make connection with tole = {tmp_role_junior.name} + connect '{THIS_COMPUTER_NAME}:{act.db.db_path}'; + + set list on; + select 'point-1' as msg, v.* from v_info v; + + -- MUST FAIL because neither user nor its role has no access rights to the 'TEST' table: + select count(*) as test_rows from test; + commit; + + -- Make temporary connection as SYSDBA and change mapping from predefined_group domain_any_rid_admins + -- so that any connection can get {tmp_role_senior.name} role as trusted role: + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + + drop mapping win_admins1; + grant {tmp_role_junior.name} to public; + + -- Following statement means that any attachment will be granted with role + -- which, in turn was granted for SELECT from table 'test': + create or alter mapping win_admins2 using plugin win_sspi from predefined_group domain_any_rid_admins to role {tmp_role_senior.name}; + commit; + + connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role_junior.name.upper()}; + + select 'point-2' as msg, v.* from v_info v; + + set bail on; + set term ^; + execute block as + begin + -- Following statement: + -- 1) must pass without any error; + -- 2) leads to change effective role from {tmp_role_junior.name} to {tmp_role_senior.name}: + -- NB: if current OS user has no admin rights then following error will raise at this point: + -- Statement failed, SQLSTATE = 0P000 + -- Your attachment has no trusted role + set trusted role; + end + ^ + set term ;^ + commit; + set bail off; + + select 'point-3' as msg, v.* from v_info v; + -- this MUST PASS because of trusted role {tmp_role_senior.name} whic has needed access rights: + select count(*) as test_rows from test; + commit; + """ + + expected_out = f""" + MSG point-1 + MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} + MON$ROLE {tmp_role_junior.name.upper()} + MON$REMOTE_PROTOCOL TCP + MON$AUTH_METHOD Mapped from Win_Sspi + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} + + MSG point-2 + MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} + MON$ROLE {tmp_role_junior.name.upper()} + MON$REMOTE_PROTOCOL TCP + MON$AUTH_METHOD Mapped from Win_Sspi + + MSG point-3 + MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} + MON$ROLE {tmp_role_senior.name.upper()} + MON$REMOTE_PROTOCOL TCP + MON$AUTH_METHOD Mapped from Win_Sspi + TEST_ROWS 0 + """ + + act.expected_stdout = expected_out + act.isql(switches=['-q'], input = sql_check, connect_db=False, credentials = False, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 7d33bebd8b13e1cb6ec8c9a2ec80e906867e6705 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 2 Aug 2024 21:47:26 +0300 Subject: [PATCH 0101/1064] Added alias needed for test bugs/gh_8194_test.py --- files/qa-databases.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index 0bd50daa..8ef4f321 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -256,6 +256,12 @@ tmp_gh_8062_alias = $(dir_sampleDb)/qa/tmp_gh_8062.fdb SecurityDatabase = tmp_gh_8062_alias } +# Test issue: https://github.com/FirebirdSQL/firebird/issues/8194 +tmp_gh_8194_alias = $(dir_sampleDb)/qa/tmp_gh_8194.fdb +{ + DefaultDbCachePages = 128 +} + # Databases for replication tests: # From eec847251488b38c9d390a56d03c760bb3151a07 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 2 Aug 2024 21:47:53 +0300 Subject: [PATCH 0102/1064] Added/Updated tests\bugs\gh_8194_test.py: Checked on 6.0.0.406 - all fine. --- tests/bugs/gh_8194_test.py | 88 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/bugs/gh_8194_test.py diff --git a/tests/bugs/gh_8194_test.py b/tests/bugs/gh_8194_test.py new file mode 100644 index 00000000..859bc37b --- /dev/null +++ b/tests/bugs/gh_8194_test.py @@ -0,0 +1,88 @@ +#coding:utf-8 + +#coding:utf-8 + +""" +ID: issue-8194 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8194 +TITLE: Internal consistency check (page in use during flush) with small number of DefaultDbCachePages +DESCRIPTION: + Test uses pre-created databases.conf which has alias (see variable REQUIRED_ALIAS) with DefaultDbCachePages = 128. + Database file for that alias must NOT exist in the QA_root/files/qa/ subdirectory: it will be created here. +NOTES: + [02.08.2024] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + 3. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + 4. Custom driver config object ('db_cfg_object') is used: we have to use DB with predefined alias instead of temporary one. + 5. It is enough to set number of iterations to small number about 10...20 (see 'LOOP_LIMIT'): bugcheck raised after first 2...3 iter. + + Confirmed bug on 6.0.0.403, got in firebird.log: + internal Firebird consistency check (page in use during flush (210), file: cch.cpp line: 2827) + Checked on 6.0.0.406 - all fine. +""" + +import re +from pathlib import Path +import pytest +from firebird.qa import * +from firebird.driver import driver_config, create_database, NetProtocol + +substitutions = [('[ \t]+', ' '), ] +REQUIRED_ALIAS = 'tmp_gh_8194_alias' +LOOP_LIMIT = 20 +SUCCESS_MSG = 'OK.' + +db = db_factory() +act = python_act('db') + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + if act.get_server_architecture() != 'SuperServer': + pytest.skip('Applies only to SuperServer') + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_8194_alias = $(dir_sampleDb)/qa/tmp_qa_8194.fdb + # - then we extract filename: 'tmp_qa_8194.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + srv_cfg = """ + [local] + host = localhost + user = SYSDBA + password = masterkey + """ + srv_cfg = driver_config.register_server(name = 'test_srv_gh_8194', config = '') + + db_cfg_name = 'tmp_8194' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = REQUIRED_ALIAS + for i in range(LOOP_LIMIT): + with create_database(db_cfg_name, user = act.db.user, password = act.db.password, charset = 'utf8') as con: + con.drop_database() + + print(SUCCESS_MSG) + + act.expected_stdout = SUCCESS_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From b17f7ce10cec167ef02f242499e234d4d8657b08 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 2 Aug 2024 21:51:17 +0300 Subject: [PATCH 0103/1064] Added/Updated tests\bugs\gh_8194_test.py: minor change: added note about mandatory charset = utf8 --- tests/bugs/gh_8194_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/bugs/gh_8194_test.py b/tests/bugs/gh_8194_test.py index 859bc37b..2d8081a0 100644 --- a/tests/bugs/gh_8194_test.py +++ b/tests/bugs/gh_8194_test.py @@ -78,6 +78,9 @@ def test_1(act: Action, capsys): db_cfg_object.protocol.value = NetProtocol.INET db_cfg_object.database.value = REQUIRED_ALIAS for i in range(LOOP_LIMIT): + # ::: NB ::: + # charset must be 'utf8' otherwise problem can not be reproduced! + # (see also note by the author of ticket in his starting message) with create_database(db_cfg_name, user = act.db.user, password = act.db.password, charset = 'utf8') as con: con.drop_database() From 75f4c58a57c407d4ee6eac7648f126024f903a01 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 3 Aug 2024 09:36:52 +0300 Subject: [PATCH 0104/1064] Added/Updated tests\bugs\core_6469_test.py: minor change: added forgotten upper() calls --- tests/bugs/core_6469_test.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_6469_test.py b/tests/bugs/core_6469_test.py index 357dfb37..193b8c5e 100644 --- a/tests/bugs/core_6469_test.py +++ b/tests/bugs/core_6469_test.py @@ -81,7 +81,7 @@ db = db_factory() -act = python_act('db') +act = python_act('db', substitutions = [('[ \t]+', ' '), ]) tmp_role = role_factory('db', name='TMP$R6469') tmp_file = temp_file('c6469_tmp.sql') @@ -171,7 +171,9 @@ def run_script(act: Action, tmp_role: Role, tmp_file: Path): connect '{THIS_COMPUTER_NAME}:{act.db.db_path}' role {tmp_role.name}; - select mon$user,mon$role,mon$auth_method from mon$attachments where mon$attachment_id = current_connection; + select upper(mon$user) as mon_user, upper(mon$role) as mon_role, mon$auth_method as mon_auth + from mon$attachments + where mon$attachment_id = current_connection; commit; set trusted role; @@ -185,10 +187,11 @@ def run_script(act: Action, tmp_role: Role, tmp_file: Path): tmp_file.write_text(script) act.expected_stdout = f""" - MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} - MON$ROLE {tmp_role.name.upper()} - MON$AUTH_METHOD Mapped from Win_Sspi + MON_USER {THIS_COMPUTER_NAME.upper()}\\{CURRENT_WIN_ADMIN.upper()} + MON_ROLE {tmp_role.name.upper()} + MON_AUTH Mapped from Win_Sspi """ + act.isql(switches=['-n', '-q'], input_file = tmp_file, connect_db = False, credentials = False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout act.reset() From 30753d7217bd10ed1cc7e8741c4492959b37a008 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 4 Aug 2024 17:03:06 +0300 Subject: [PATCH 0105/1064] Added/Updated tests\bugs\gh_7257_misc_datatypes_test.py: Checked on 6.0.0.409, 5.0.1.1469 --- tests/bugs/gh_7257_misc_datatypes_test.py | 126 ++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 tests/bugs/gh_7257_misc_datatypes_test.py diff --git a/tests/bugs/gh_7257_misc_datatypes_test.py b/tests/bugs/gh_7257_misc_datatypes_test.py new file mode 100644 index 00000000..8fcaa582 --- /dev/null +++ b/tests/bugs/gh_7257_misc_datatypes_test.py @@ -0,0 +1,126 @@ +#coding:utf-8 + +""" +ID: issue-7257 +ISSUE: 7257 +TITLE: Support for partial indices +DESCRIPTION: + Additional test to check misc datatypes in partial indices. +NOTES: + Checked on 6.0.0.409, 5.0.1.1469 +""" + +import pytest +from firebird.qa import * +from decimal import Decimal + +db = db_factory() +act = python_act('db', substitutions = [('[ \t]+', ' '), ]) + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +def run_ddl_dml(act, capsys, dtype, v_chk, v_max, use_rand = True): + + with act.db.connect() as con: + cur = con.cursor() + idx_partial_name = f'test_f01_{dtype.split()[0]}_partial'.upper() + idx_common_name = f'test_f02_{dtype.split()[0]}_common'.upper() + if dtype =='date': + v_chk = 'current_date' + insert_sttm = f"insert into test(id, f01) select row_number()over(), iif(mod(row_number()over(), 100) = 0, {v_chk}, dateadd(rand()*1000 day to date '01.01.2000')) from rdb$types,rdb$types rows 1000" + elif dtype == 'time with time zone': + v_chk = "time '11:11:11.111 Indian/Cocos'" + insert_sttm = f"insert into test(id, f01) select row_number()over(), iif(mod(row_number()over(), 100) = 0, {v_chk}, time '11:11:11.111 Pacific/Fiji' ) from rdb$types,rdb$types rows 1000" + elif dtype == 'varchar(80) character set utf8': + idx_partial_name = f'test_f01_utf8_partial'.upper() + idx_common_name = f'test_f02_utf8_common'.upper() + v_chk = "'Sporvognsskinneskidtskraberkonduktørbuksebæltespændeemblempoleringsmiddelshylde€'" + v_max = "'Minoritetsladningsbærerdiffusjonskoeffisientmålingsapparatur'" + insert_sttm = f"insert into test(id, f01) select row_number()over(),iif(mod(row_number()over(), 100) = 0, {v_chk}, {v_max}) from rdb$types,rdb$types rows 1000" + elif dtype == 'varbinary(16)': + idx_partial_name = f'test_f01_vbin_partial'.upper() + idx_common_name = f'test_f02_vbin_common'.upper() + v_chk = "x'0A'" + v_max = "gen_uuid()" + insert_sttm = f"insert into test(id, f01) select row_number()over(),iif(mod(row_number()over(), 100) = 0, {v_chk}, {v_max}) from rdb$types,rdb$types rows 1000" + elif dtype == 'boolean': + v_chk = "false" + v_max = "true" + insert_sttm = f"insert into test(id, f01) select row_number()over(),iif(mod(row_number()over(), 100) = 0, {v_chk}, {v_max}) from rdb$types,rdb$types rows 1000" + else: + insert_sttm = f"insert into test(id, f01) select row_number()over(), iif(mod(row_number()over(), 100) = 0, cast({v_chk} as {dtype}), cast(rand()*{v_max} as {dtype})) from rdb$types,rdb$types rows 1000" + ddl = f""" + recreate table test(id int primary key, f01 {dtype}, f02 {dtype}) ^ + {insert_sttm} ^ + update test set f02 = f01 ^ + create index {idx_partial_name} on test computed by (f01) where f01 = {v_chk} ^ + create index {idx_common_name} on test(f02) ^ + set statistics index {idx_partial_name} ^ + set statistics index {idx_common_name} ^ + """ + + dml = f""" + select count(*) from test where f01 = {v_chk} ^ + select count(*) from test where f02 = {v_chk} ^ + """ + + for x in [p for p in ddl.split('^') if p.strip()]: + if x.startswith('--'): + pass + else: + con.execute_immediate(x) + con.commit() + + for x in [p for p in dml.split('^') if p.strip()]: + ps = cur.prepare(x) + for s in ps.detailed_plan.split('\n'): + print( replace_leading(s) ) + + cur.execute(ps) + cur_cols = cur.description + for r in cur: + for i in range(0,len(cur_cols)): + print( cur_cols[i][0], ':', r[i] ) + con.commit() + + act.expected_stdout = f""" + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST" Access By ID + ................-> Bitmap + ....................-> Index "{idx_partial_name}" Full Scan + COUNT : 10 + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST" Access By ID + ................-> Bitmap + ....................-> Index "{idx_common_name}" Range Scan (full match) + COUNT : 10 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + run_ddl_dml(act, capsys, 'smallint', -32768, 32767, True) + run_ddl_dml(act, capsys, 'bigint', -9223372036854775808, 9223372036854775807, True) + run_ddl_dml(act, capsys, 'double precision', -2.2250738585072014e-308, 1.7976931348623158e+308, True) + run_ddl_dml(act, capsys, 'int128', Decimal(-170141183460469231731687303715884105728), Decimal(170141183460469231731687303715884105727), True) + run_ddl_dml(act, capsys, 'decfloat', 0, Decimal(1.7976931348623158e+308), True) + run_ddl_dml(act, capsys, 'date', None, None) + run_ddl_dml(act, capsys, 'time with time zone', None, None) + run_ddl_dml(act, capsys, 'varchar(80) character set utf8', None, None) + run_ddl_dml(act, capsys, 'varbinary(16)', None, None) + run_ddl_dml(act, capsys, 'boolean', None, None) From 1599c74fab060da3a669b9f9747fc77703d7d779 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 5 Aug 2024 23:13:42 +0300 Subject: [PATCH 0106/1064] Added/Updated tests\bugs\gh_8187_test.py: Checked on Windows, 6.0.0.406 (SS and CS). --- tests/bugs/gh_8187_test.py | 128 +++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 tests/bugs/gh_8187_test.py diff --git a/tests/bugs/gh_8187_test.py b/tests/bugs/gh_8187_test.py new file mode 100644 index 00000000..e095433d --- /dev/null +++ b/tests/bugs/gh_8187_test.py @@ -0,0 +1,128 @@ +#coding:utf-8 + +""" +ID: issue-8187 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8187 +TITLE: Performance regression in generating of UUID values after introducing GUID-v7 +DESCRIPTION: + We can estimate perfomance by comparison of time that is spent to generate UUIDs vs result of some crypt function + (commit: https://github.com/FirebirdSQL/firebird/commit/43e40886856ace39e0b3a1de7b00c53325e67225). + Function crypt_hash( using SHA512) has been selected for that. + Two procedures are created for generating appropriate results, SP_GEN_UUID and SP_GEN_HASH. + Duration for each of them is measured as difference between psutil.Process(fb_pid).cpu_times() counters. + We do these measures times for each SP, and each result is added to the list + which, in turn, is the source for median evaluation. + Finally, we get ratio between minimal and maximal medians (see 'median_ratio') + + Test is considered as passed if median_ratio less than threshold . +NOTES: + [05.08.2024] pzotov. + It seems that SP_CRYPT_HASH consumes lot of CPU resources thus it must be called much less times than SP_GEN_UUID, + see settings N_COUNT_PER_MEASURE_HASH vs N_COUNT_PER_MEASURE_GUID. + On Windows 10 usually ratio between cpu_times() medians of these two SPs is about 0.5 (before fix it was about 30). + + Confirmed bug on 6.0.0.405. + Checked on Windows, 6.0.0.406 (SS and CS). +""" + +import psutil +import pytest +from firebird.qa import * + +#-------------------------------------------------------------------- +def median(lst): + n = len(lst) + s = sorted(lst) + return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None +#-------------------------------------------------------------------- + +########################### +### S E T T I N G S ### +########################### + +# How many times we call procedures: +N_MEASURES = 11 + +# How many iterations must be done: +N_COUNT_PER_MEASURE_HASH = 1000 + +N_COUNT_PER_MEASURE_GUID = 100000 + +# Maximal value for ratio between maximal and minimal medians +# +MAX_RATIO = 1 +############# + +init_script = \ +f''' + set term ^; + create or alter procedure sp_gen_uuid (n_cnt int) as + declare v_guid varchar(16) character set octets; + begin + while (n_cnt > 0) do + begin + v_guid = gen_uuid(); + n_cnt = n_cnt - 1; + end + end + ^ + create or alter procedure sp_gen_hash (n_cnt int) as + declare v_hash varbinary(64); + declare s varchar(32765); + begin + s = lpad('', 32765, uuid_to_char(gen_uuid())); + while (n_cnt > 0) do + begin + v_hash = crypt_hash(s using SHA512); + n_cnt = n_cnt - 1; + end + end + ^ + commit + ^ +''' + +db = db_factory(init = init_script, charset = 'win1251') +act = python_act('db') + +expected_stdout = """ + Medians ratio: acceptable +""" + +@pytest.mark.version('>=4.0.5') +def test_1(act: Action, capsys): + + with act.db.connect(charset = 'win1251') as con: + cur=con.cursor() + cur.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur.fetchone()[0]) + + sp_time = {} + for i in range(0, N_MEASURES): + for sp_name in ('sp_gen_hash', 'sp_gen_uuid', ): + fb_info_init = psutil.Process(fb_pid).cpu_times() + n_cnt = N_COUNT_PER_MEASURE_HASH if sp_name == 'sp_gen_hash' else N_COUNT_PER_MEASURE_GUID + cur.callproc( sp_name, (n_cnt,) ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + sp_time[ sp_name, i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + + sp_gen_hash_median = median([v for k,v in sp_time.items() if k[0] == 'sp_gen_hash']) + sp_gen_uuid_median = median([v for k,v in sp_time.items() if k[0] == 'sp_gen_uuid']) + #---------------------------------- + #print(f'{sp_gen_hash_median=}') + #print(f'{sp_gen_uuid_median=}') + + median_ratio = sp_gen_uuid_median / sp_gen_hash_median + + print( 'Medians ratio: ' + ('acceptable' if median_ratio <= MAX_RATIO else '/* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:9g}'.format(median_ratio), '{:9g}'.format(MAX_RATIO) ) ) ) + if median_ratio > MAX_RATIO: + print('CPU times for each of {N_MEASURES} measures:') + for sp_name in ('sp_gen_hash', 'sp_gen_uuid', ): + print(f'{sp_name=}:') + for p in [v for k,v in sp_time.items() if k[0] == sp_name]: + print(p) + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 2aa929c2ab8e89328ff43cb71b149fa73cc7dbc7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 5 Aug 2024 23:16:37 +0300 Subject: [PATCH 0107/1064] Added/Updated tests\bugs\gh_8187_test.py: minor change: added checked versions in comment. --- tests/bugs/gh_8187_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8187_test.py b/tests/bugs/gh_8187_test.py index e095433d..4b982e31 100644 --- a/tests/bugs/gh_8187_test.py +++ b/tests/bugs/gh_8187_test.py @@ -22,7 +22,7 @@ On Windows 10 usually ratio between cpu_times() medians of these two SPs is about 0.5 (before fix it was about 30). Confirmed bug on 6.0.0.405. - Checked on Windows, 6.0.0.406 (SS and CS). + Checked on Windows, 6.0.0.406, 5.0.1.1469, 4.0.5.3139 (SS and CS). """ import psutil From c9ff6c7cc916de5411021edab33d2eb034d77c88 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:02:29 +0300 Subject: [PATCH 0108/1064] Added/Updated tests\functional\index\alter\test_04.py: Splitted expected* text because system triggers now are created in C++/GDML code --- tests/functional/index/alter/test_04.py | 40 +++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tests/functional/index/alter/test_04.py b/tests/functional/index/alter/test_04.py index d3cdae9b..914249fe 100644 --- a/tests/functional/index/alter/test_04.py +++ b/tests/functional/index/alter/test_04.py @@ -3,33 +3,43 @@ """ ID: index.alter-04 TITLE: ALTER INDEX - INACTIVE PRIMARY KEY -DESCRIPTION: +DESCRIPTION: An index participating in PK-constraint cannot be deactivated FBTEST: functional.index.alter.04 +NOTES: + [08.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13"45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import pytest from firebird.qa import * -init_script = """CREATE TABLE t( a INTEGER NOT NULL, - CONSTRAINT pkindx PRIMARY KEY(a) - ); -commit;""" - +init_script = "recreate table test(id int primary key using index test_pk);" db = db_factory(init=init_script) -test_script = """ALTER INDEX pkindx INACTIVE;""" +test_script = "alter index test_pk inactive;" act = isql_act('db', test_script) -expected_stderr = """Statement failed, SQLSTATE = 27000 -unsuccessful metadata update --ALTER INDEX PKINDX failed --action cancelled by trigger (3) to preserve data integrity --Cannot deactivate index used by a PRIMARY/UNIQUE constraint +expected_stdout_5x = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER INDEX TEST_PK failed + -action cancelled by trigger (3) to preserve data integrity + -Cannot deactivate index used by a PRIMARY/UNIQUE constraint +""" +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER INDEX TEST_PK failed + -Cannot deactivate index used by a PRIMARY/UNIQUE constraint """ + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 55f51e5a3de9d0689f1c2a453a3f21e68bb1c3d8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:08:47 +0300 Subject: [PATCH 0109/1064] Added/Updated tests\functional\index\alter\test_04.py: minor change: removed empty line --- tests/functional/index/alter/test_04.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/index/alter/test_04.py b/tests/functional/index/alter/test_04.py index 914249fe..6c581c53 100644 --- a/tests/functional/index/alter/test_04.py +++ b/tests/functional/index/alter/test_04.py @@ -37,7 +37,6 @@ -Cannot deactivate index used by a PRIMARY/UNIQUE constraint """ - @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 030a0e0946fdc4ca6382a99ae35ba6a62edd1d26 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:09:00 +0300 Subject: [PATCH 0110/1064] Added/Updated tests\functional\index\alter\test_05.py: Splitted expected* text because system triggers now are created in C++/GDML code --- tests/functional/index/alter/test_05.py | 50 +++++++++++++++---------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/tests/functional/index/alter/test_05.py b/tests/functional/index/alter/test_05.py index 69aebf92..447c9247 100644 --- a/tests/functional/index/alter/test_05.py +++ b/tests/functional/index/alter/test_05.py @@ -3,37 +3,49 @@ """ ID: index.alter-05 TITLE: ALTER INDEX - INACTIVE FOREIGN KEY -DESCRIPTION: +DESCRIPTION: An index participating in FOREIGN KEY constraint cannot be deactivated FBTEST: functional.index.alter.05 +NOTES: + [08.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13"45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import pytest from firebird.qa import * -init_script = """CREATE TABLE pk( a INTEGER NOT NULL, - CONSTRAINT pkindx PRIMARY KEY(a) - ); -commit; -CREATE TABLE fk( a INTEGER NOT NULL, - CONSTRAINT fkindx FOREIGN KEY(a) REFERENCES pk(a) - ); -commit;""" +init_script = """ + recreate table test( + id int primary key using index test_pk + ,pid int references test(id) using index test_fk + ); +""" -db = db_factory(init=init_script) +db = db_factory(init = init_script) -test_script = """ALTER INDEX fkindx INACTIVE;""" +test_script = "alter index test_fk inactive;" act = isql_act('db', test_script) -expected_stderr = """Statement failed, SQLSTATE = 27000 -unsuccessful metadata update --ALTER INDEX FKINDX failed --action cancelled by trigger (2) to preserve data integrity --Cannot deactivate index used by an integrity constraint +expected_stdout_5x = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER INDEX TEST_FK failed + -action cancelled by trigger (2) to preserve data integrity + -Cannot deactivate index used by an integrity constraint +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER INDEX TEST_FK failed + -Cannot deactivate index used by an integrity constraint """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 157052b60fabe62a5ca30738bfa55432a2687f50 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:17:37 +0300 Subject: [PATCH 0111/1064] Added/Updated tests\functional\gtcs\test_ref_integ_drop_fk_index.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../gtcs/test_ref_integ_drop_fk_index.py | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_drop_fk_index.py b/tests/functional/gtcs/test_ref_integ_drop_fk_index.py index 348247c4..a1473757 100644 --- a/tests/functional/gtcs/test_ref_integ_drop_fk_index.py +++ b/tests/functional/gtcs/test_ref_integ_drop_fk_index.py @@ -4,18 +4,24 @@ ID: gtcs.ref-integ-drop-fk-index TITLE: Index that is used for FK should not be avail for DROP DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.4.ISQL.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.4.ISQL.script - This test uses pre-created script ( /files/gtcs-ref-integ-init.sql ) which creates two - tables with PK/FK referencing constraint(parent = department, child = employee). - FK-constraint uses index with name = 'ref_key', and here we try to: - * DROP this index; - * insert record in the child table which has no apropriate PK in the parent table. - (see 'sql_addi' variable which stores SQL statements for that). - Both actions should fail. + This test uses pre-created script ( /files/gtcs-ref-integ-init.sql ) which creates two + tables with PK/FK referencing constraint(parent = department, child = employee). + FK-constraint uses index with name = 'ref_key', and here we try to: + * DROP this index; + * insert record in the child table which has no apropriate PK in the parent table. + (see 'sql_addi' variable which stores SQL statements for that). + Both actions should fail. -FBTEST: functional.gtcs.ref_integ_drop_fk_index +FBTEST: functional.gtcs.ref_integ_drop_fk_index +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13"45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import pytest @@ -30,7 +36,7 @@ Records affected: 0 """ -test_expected_stderr = """ +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -DROP INDEX REF_KEY failed @@ -43,6 +49,18 @@ -Problematic key value is ("DEPT_NO" = -1) """ +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP INDEX REF_KEY failed + -Cannot delete index used by an Integrity Constraint + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "REF_KEY" on table "EMPLOYEE" + -Foreign key reference target does not exist + -Problematic key value is ("DEPT_NO" = -1) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): @@ -54,9 +72,9 @@ def test_1(act: Action): set count on; select * from employee e where e.dept_no < 0; ''' - + act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From 853f255dd3f1201cc5ac7c05e1a989e4a4844f18 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:20:50 +0300 Subject: [PATCH 0112/1064] Added/Updated tests\functional\gtcs\test_ref_integ_drop_pk_constraint.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../gtcs/test_ref_integ_drop_pk_constraint.py | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py b/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py index 787b89f4..08d44748 100644 --- a/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py +++ b/tests/functional/gtcs/test_ref_integ_drop_pk_constraint.py @@ -4,9 +4,15 @@ ID: gtcs.ref_integ_drop_pk_constraint TITLE: Constraint of PRIMARY KEY should not be avail for DROP if there is FK that depends on it DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.2.ISQL.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.2.ISQL.script FBTEST: functional.gtcs.ref_integ_drop_pk_constraint +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13"45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import os @@ -17,7 +23,11 @@ act = python_act('db') -test_expected_stderr = """ +test_expected_stdout = """ + Records affected: 0 +""" + +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -DROP INDEX DEPT_KEY failed @@ -29,10 +39,16 @@ -Problematic key value is ("DEPT_NO" = 1) """ -test_expected_stdout = """ - Records affected: 0 -""" +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP INDEX DEPT_KEY failed + -Cannot delete index used by an Integrity Constraint + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "DEPT_KEY" on table "DEPARTMENT" + -Problematic key value is ("DEPT_NO" = 1) +""" @pytest.mark.version('>=3.0') def test_1(act: Action): @@ -46,7 +62,7 @@ def test_1(act: Action): ''' act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From 4ab82edc5a5ab2e2a5ab13deeb4e5a7b8038a948 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:26:18 +0300 Subject: [PATCH 0113/1064] Added/Updated tests\functional\gtcs\test_ref_integ_drop_pk_index.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../gtcs/test_ref_integ_drop_pk_index.py | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_drop_pk_index.py b/tests/functional/gtcs/test_ref_integ_drop_pk_index.py index 3635af9e..6fe9662b 100644 --- a/tests/functional/gtcs/test_ref_integ_drop_pk_index.py +++ b/tests/functional/gtcs/test_ref_integ_drop_pk_index.py @@ -4,9 +4,15 @@ ID: gtcs.ref_integ_drop_pk_index TITLE: Index that is used for PRIMARY KEY should not be avail for DROP DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.3.ISQL.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.3.ISQL.script FBTEST: functional.gtcs.ref_integ_drop_pk_index +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13"45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import os @@ -17,7 +23,11 @@ act = python_act('db') -test_expected_stderr = """ +test_expected_stdout = """ + Records affected: 0 +""" + +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -DROP INDEX DEPT_KEY failed @@ -29,8 +39,14 @@ -Problematic key value is ("DEPT_NO" = 1) """ -test_expected_stdout = """ - Records affected: 0 +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP INDEX DEPT_KEY failed + -Cannot delete index used by an Integrity Constraint + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "DEPT_KEY" on table "DEPARTMENT" + -Problematic key value is ("DEPT_NO" = 1) """ @pytest.mark.version('>=3.0') @@ -45,7 +61,7 @@ def test_1(act: Action): ''' act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From fd73e3eaab28ac074c53cbba32a0f0ad2adfbd5b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:29:17 +0300 Subject: [PATCH 0114/1064] Added/Updated tests\functional\gtcs\test_ref_integ_inactive_fk_index.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../gtcs/test_ref_integ_inactive_fk_index.py | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py b/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py index 652e6186..d6bb0c14 100644 --- a/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py +++ b/tests/functional/gtcs/test_ref_integ_inactive_fk_index.py @@ -4,9 +4,15 @@ ID: gtcs.ref_integ_inactive_fk_index TITLE: Index that is used for FK should not be avail for INACTIVE DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.8.ISQL.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.8.ISQL.script FBTEST: functional.gtcs.ref_integ_inactive_fk_index +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13:45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import os import pytest @@ -16,7 +22,11 @@ act = python_act('db') -test_expected_stderr = """ +test_expected_stdout = """ + Records affected: 0 +""" + +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -ALTER INDEX REF_KEY failed @@ -29,8 +39,16 @@ -Problematic key value is ("DEPT_NO" = -1) """ -test_expected_stdout = """ - Records affected: 0 +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER INDEX REF_KEY failed + -Cannot deactivate index used by an integrity constraint + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "REF_KEY" on table "EMPLOYEE" + -Foreign key reference target does not exist + -Problematic key value is ("DEPT_NO" = -1) """ @pytest.mark.version('>=3.0') @@ -49,7 +67,7 @@ def test_1(act: Action): ''' act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From 47b81fc6f463175fa63ca62ef39f86ed92bdd2d4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:31:43 +0300 Subject: [PATCH 0115/1064] Added/Updated tests\functional\gtcs\test_ref_integ_inactive_pk_index.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../gtcs/test_ref_integ_inactive_pk_index.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py b/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py index 5370494d..de76cb43 100644 --- a/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py +++ b/tests/functional/gtcs/test_ref_integ_inactive_pk_index.py @@ -7,6 +7,12 @@ Original test see in: https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.7.ISQL.script FBTEST: functional.gtcs.ref_integ_inactive_pk_index +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13:45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import os @@ -17,7 +23,11 @@ act = python_act('db') -test_expected_stderr = """ +test_expected_stdout = """ + Records affected: 1 +""" + +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -ALTER INDEX DEPT_KEY failed @@ -28,9 +38,15 @@ violation of PRIMARY or UNIQUE KEY constraint "DEPT_KEY" on table "DEPARTMENT" -Problematic key value is ("DEPT_NO" = 1) """ +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER INDEX DEPT_KEY failed + -Cannot deactivate index used by an integrity constraint -test_expected_stdout = """ - Records affected: 1 + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "DEPT_KEY" on table "DEPARTMENT" + -Problematic key value is ("DEPT_NO" = 1) """ @pytest.mark.version('>=3.0') @@ -55,7 +71,7 @@ def test_1(act: Action): ''' act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From bd5fe2c0df21f889d4381797f106269068f30255 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:38:58 +0300 Subject: [PATCH 0116/1064] Added/Updated tests\functional\gtcs\test_ref_integ_inactive_pk_index_2.py: Splitted expected* text because system triggers now are created in C++/GDML code --- .../test_ref_integ_inactive_pk_index_2.py | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/tests/functional/gtcs/test_ref_integ_inactive_pk_index_2.py b/tests/functional/gtcs/test_ref_integ_inactive_pk_index_2.py index eb4d9d36..f25e8dfc 100644 --- a/tests/functional/gtcs/test_ref_integ_inactive_pk_index_2.py +++ b/tests/functional/gtcs/test_ref_integ_inactive_pk_index_2.py @@ -4,17 +4,24 @@ ID: gtcs.ref_integ_inactive_pk_index_2 TITLE: Index that is used for PRIMARY KEY should not be avail for INACTIVE DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.7.ISQL.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/REF_INT.7.ISQL.script - NOTE on difference from GTCS/tests/REF_INT.7.ISQL: - we attampt to insert into child table (employee) record which VIOLATES ref. integrity. - See quote from source test: - attempts to insert records into another table in violation of the referential - integrity constraint. The current behaviour is that even though the - unique index has been inactivated, the insertion fails because of referential - integrity violation.. (bug 7517) + NOTE on difference from GTCS/tests/REF_INT.7.ISQL: + we attampt to insert into child table (employee) record which VIOLATES ref. integrity. + See quote from source test: + attempts to insert records into another table in violation of the referential + integrity constraint. The current behaviour is that even though the + unique index has been inactivated, the insertion fails because of referential + integrity violation.. (bug 7517) FBTEST: functional.gtcs.ref_integ_inactive_pk_index_2 +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13:45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 + """ import os @@ -25,7 +32,11 @@ act = python_act('db') -test_expected_stderr = """ +test_expected_stdout = """ + Records affected: 0 +""" + +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -ALTER INDEX DEPT_KEY failed @@ -38,10 +49,17 @@ -Problematic key value is ("DEPT_NO" = -1) """ -test_expected_stdout = """ - Records affected: 0 -""" +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER INDEX DEPT_KEY failed + -Cannot deactivate index used by an integrity constraint + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "REF_KEY" on table "EMPLOYEE" + -Foreign key reference target does not exist + -Problematic key value is ("DEPT_NO" = -1) +""" @pytest.mark.version('>=3.0') def test_1(act: Action): @@ -55,7 +73,7 @@ def test_1(act: Action): ''' act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.isql(switches=['-q'], input = os.linesep.join( (sql_init, sql_addi) ) ) From 986f83d3a7c8b8615840ecffff5fa8b4e446c5fc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 7 Aug 2024 01:41:24 +0300 Subject: [PATCH 0117/1064] Added/Updated tests\bugs\core_4725_test.py: Splitted expected* text because system triggers now are created in C++/GDML code --- tests/bugs/core_4725_test.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4725_test.py b/tests/bugs/core_4725_test.py index 17dfe52a..4352efbd 100644 --- a/tests/bugs/core_4725_test.py +++ b/tests/bugs/core_4725_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4725 FBTEST: bugs.core_4725 +NOTES: + [07.08.2024] pzotov + Splitted expected* text because system triggers now are created in C++/GDML code + See https://github.com/FirebirdSQL/firebird/pull/8202 + Commit (05-aug-2024 13:45): + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 """ import pytest @@ -213,7 +219,7 @@ DM_06 INTEGER Not Null """ -expected_stderr = """ +expected_stderr_5x = """ Statement failed, SQLSTATE = 27000 unsuccessful metadata update -ALTER TABLE TEST00 failed @@ -239,10 +245,34 @@ validation error for column "TEST06"."X", value "*** null ***" """ +expected_stderr_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST00 failed + -Column used in a PRIMARY constraint must be NOT NULL. + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST01 failed + -Column used in a PRIMARY constraint must be NOT NULL. + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DM_03 failed + -Domain used in the PRIMARY KEY constraint of table TEST03 must be NOT NULL + + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field X of table TEST05 NOT NULL because there are NULLs present + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST06"."X", value "*** null ***" +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr + act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x act.execute() assert (act.clean_stderr == act.clean_expected_stderr and act.clean_stdout == act.clean_expected_stdout) From 3db2709f83722999a3408c7eaeb87601010d51bb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 8 Aug 2024 10:40:41 +0300 Subject: [PATCH 0118/1064] Added/Updated tests\bugs\core_4731_test.py: Separated code for FB-6x because it became differ after implemented GH-8202 --- tests/bugs/core_4731_test.py | 38 +++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_4731_test.py b/tests/bugs/core_4731_test.py index c439c943..673b65fd 100644 --- a/tests/bugs/core_4731_test.py +++ b/tests/bugs/core_4731_test.py @@ -40,11 +40,15 @@ 8) select expressions that were PASSED without exceptions. NOTES: [18.02.2020] pzotov - REFACTORED: most of initial code was moved into $files_location/core_4731.sql; changed test_type to 'Python'. + REFACTORED: most of initial code was moved into $files_location/core_4731.sql; changed test_type to 'Python'. [04.03.2023] pzotov - Separated code for FB-4x because it allows now statement 'delete from RDB$BACKUP_HISTORY ...' - Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. - + Separated code for FB-4x because it allows now statement 'delete from RDB$BACKUP_HISTORY ...' + Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. + [08.08.2024] pzotov + Separated code for FB-6x because it became differ after implemented GH-8202 + https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 + (05-aug-2024 13:45, "Regenerate system triggers improving formatting and constant names") + Checked on 6.0.0.419-3505a5e JIRA: CORE-4731 FBTEST: bugs.core_4731 """ @@ -129,6 +133,30 @@ -- gdscode list for blocked: 335544926 """ +fb6x_expected_out = """ + -- Executed with role: NONE. Expressions that passes WITHOUT errors: + -- count_of_passed: 0 + -- gdscode list for blocked: 335544926 + -- Executed with role: RDB$ADMIN. Expressions that passes WITHOUT errors: + -- count_of_passed: 14 + VULNERABLE_EXPR delete from RDB$BACKUP_HISTORY t rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR insert into RDB$BACKUP_HISTORY(RDB$BACKUP_ID , RDB$TIMESTAMP , RDB$BACKUP_LEVEL , RDB$GUID , RDB$SCN , RDB$FILE_NAME) values(null, null, null, null, null, null) returning rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR delete from RDB$DB_CREATORS t rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR insert into RDB$DB_CREATORS(RDB$USER , RDB$USER_TYPE) values(null, null) returning rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$DB_CREATORS t set t.RDB$USER = 'C' rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$DB_CREATORS t set t.RDB$USER = null rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$DB_CREATORS t set t.RDB$USER_TYPE = 32767 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$DB_CREATORS t set t.RDB$USER_TYPE = null rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$FUNCTIONS t set t.RDB$FUNCTION_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$PACKAGES t set t.RDB$PACKAGE_BODY_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$PACKAGES t set t.RDB$PACKAGE_HEADER_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$PROCEDURES t set t.RDB$PROCEDURE_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$RELATIONS t set t.RDB$VIEW_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + VULNERABLE_EXPR update RDB$TRIGGERS t set t.RDB$TRIGGER_SOURCE = null where coalesce(rdb$system_flag,0)=0 rows 1 returning t.rdb$db_key; -- length of returned rdb$dbkey=8 + -- gdscode list for blocked: 335544926 + +""" + @pytest.mark.version('>=3.0') def test_1(act: Action, dba_privileged_user: User, non_privileged_user: User, capsys): # Run prepare script @@ -225,6 +253,6 @@ def test_1(act: Action, dba_privileged_user: User, non_privileged_user: User, ca commit; """ - act.expected_stdout = fb3x_expected_out if act.is_version('<4') else fb4x_expected_out + act.expected_stdout = fb3x_expected_out if act.is_version('<4') else fb4x_expected_out if act.is_version('<6') else fb6x_expected_out act.isql(switches=['-q'], input=test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From c4eb110236e8df1d1d4c6c68f207c410ffb7225d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 8 Aug 2024 13:03:05 +0300 Subject: [PATCH 0119/1064] Added/Updated tests\bugs\gh_8187_test.py: Separated definition of MAX_RATIO value, it depends on OS. --- tests/bugs/gh_8187_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8187_test.py b/tests/bugs/gh_8187_test.py index 4b982e31..8ffffb0f 100644 --- a/tests/bugs/gh_8187_test.py +++ b/tests/bugs/gh_8187_test.py @@ -23,6 +23,10 @@ Confirmed bug on 6.0.0.405. Checked on Windows, 6.0.0.406, 5.0.1.1469, 4.0.5.3139 (SS and CS). + + [08.08.2024] pzotov + Separated definition of MAX_RATIO value, it depends on OS. + Linux results show that medians ratio is about 2.3 ... 2.6. """ import psutil @@ -50,8 +54,9 @@ def median(lst): # Maximal value for ratio between maximal and minimal medians # -MAX_RATIO = 1 -############# +########################################### +MAX_RATIO = 1.0 if os.name == 'nt' else 5.5 +########################################### init_script = \ f''' From 74c17c4b9d969141597cd02a1c1d40d0d94f999f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 8 Aug 2024 15:44:45 +0300 Subject: [PATCH 0120/1064] Added/Updated tests\bugs\gh_8187_test.py: added forgotten import --- tests/bugs/gh_8187_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8187_test.py b/tests/bugs/gh_8187_test.py index 8ffffb0f..f9389116 100644 --- a/tests/bugs/gh_8187_test.py +++ b/tests/bugs/gh_8187_test.py @@ -28,7 +28,7 @@ Separated definition of MAX_RATIO value, it depends on OS. Linux results show that medians ratio is about 2.3 ... 2.6. """ - +import os import psutil import pytest from firebird.qa import * From e9648946dd6f80a9961c5e23d7cfbcb4086ecc18 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 9 Aug 2024 19:30:42 +0300 Subject: [PATCH 0121/1064] Added/Updated tests\bugs\core_5231_test.py: added combine_output=True in order to see STDERR text in mismatch --- tests/bugs/core_5231_test.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_5231_test.py b/tests/bugs/core_5231_test.py index 4519b083..326ddeef 100644 --- a/tests/bugs/core_5231_test.py +++ b/tests/bugs/core_5231_test.py @@ -2,15 +2,15 @@ """ ID: issue-5510 -ISSUE: 5510 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5510 TITLE: EXECUTE STATEMENT: BLR error if more than 256 output parameters exist DESCRIPTION: - We define here number of output args for which one need to made test - see var 'sp_args_count'. - Then we open .sql file and GENERATE it content based on value of 'sp_args_count' (procedure will - have header and body with appropriate number of arguments and statement to be executed). - Finally, we run ISQL subprocess with giving to it for execution just generated .sql script. - ISQL should _not_ issue any error and all lines of its STDOUT should start from the names of - output arguments (letter 'O': O1, O2, ... O5000). + We define here number of output args for which one need to made test - see var 'sp_args_count'. + Then we open .sql file and GENERATE it content based on value of 'sp_args_count' (procedure will + have header and body with appropriate number of arguments and statement to be executed). + Finally, we run ISQL subprocess with giving to it for execution just generated .sql script. + ISQL should _not_ issue any error and all lines of its STDOUT should start from the names of + output arguments (letter 'O': O1, O2, ... O5000). JIRA: CORE-5231 FBTEST: bugs.core_5231 """ @@ -71,5 +71,5 @@ def build_script(ddl_script: Path): @pytest.mark.version('>=3.0') def test_1(act: Action, ddl_script: Path): build_script(ddl_script) - act.isql(switches=[], input_file=ddl_script, charset='NONE') + act.isql(switches=[], input_file=ddl_script, charset='NONE', combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From cc1fbc5d3b9d9302fb9547f27006e1bd8f32f068 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 11 Aug 2024 09:18:45 +0300 Subject: [PATCH 0122/1064] Added/Updated tests\bugs\gh_8211_test.py: Checked on intermediate snapshots: 6.0.0.431-16bb157; 5.0.2.1477-c71eb20; 4.0.6.3141 --- tests/bugs/gh_8211_test.py | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/bugs/gh_8211_test.py diff --git a/tests/bugs/gh_8211_test.py b/tests/bugs/gh_8211_test.py new file mode 100644 index 00000000..4650a235 --- /dev/null +++ b/tests/bugs/gh_8211_test.py @@ -0,0 +1,50 @@ +#coding:utf-8 + +""" +ID: issue-8211 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8211 +TITLE: DATEADD truncates milliseconds for month and year deltas. +DESCRIPTION: +NOTES: + [11.08.2024] pzotov + Confirmed bug on 6.0.0.423 + Checked on intermediate snapshots: 6.0.0.431-16bb157; 5.0.2.1477-c71eb20; 4.0.6.3141 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + select + ''||dateadd(0 millisecond to cast('01.01.2001 01:01:01.1111' as timestamp)) a_millisecond, + ''||dateadd(0 second to cast('01.01.2001 01:01:01.1111' as timestamp)) a_second, + ''||dateadd(0 minute to cast('01.01.2001 01:01:01.1111' as timestamp)) a_minute, + ''||dateadd(0 hour to cast('01.01.2001 01:01:01.1111' as timestamp)) a_hour, + ''||dateadd(0 day to cast('01.01.2001 01:01:01.1111' as timestamp)) a_day, + ''||dateadd(0 week to cast('01.01.2001 01:01:01.1111' as timestamp)) a_week, + ''||dateadd(0 month to cast('01.01.2001 01:01:01.1111' as timestamp)) a_month, + ''||dateadd(0 year to cast('01.01.2001 01:01:01.1111' as timestamp)) a_year + from rdb$database; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + A_MILLISECOND 2001-01-01 01:01:01.1111 + A_SECOND 2001-01-01 01:01:01.1111 + A_MINUTE 2001-01-01 01:01:01.1111 + A_HOUR 2001-01-01 01:01:01.1111 + A_DAY 2001-01-01 01:01:01.1111 + A_WEEK 2001-01-01 01:01:01.1111 + A_MONTH 2001-01-01 01:01:01.1111 + A_YEAR 2001-01-01 01:01:01.1111 +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 77146b3ba88b74728b6c062929a51d37ef1d4555 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 11 Aug 2024 16:14:34 +0300 Subject: [PATCH 0123/1064] Added/Updated tests\bugs\gh_8203_test.py: Checked on 6.0.0.423, 5.0.2.1477. See notes. --- tests/bugs/gh_8203_test.py | 239 +++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 tests/bugs/gh_8203_test.py diff --git a/tests/bugs/gh_8203_test.py b/tests/bugs/gh_8203_test.py new file mode 100644 index 00000000..5604102c --- /dev/null +++ b/tests/bugs/gh_8203_test.py @@ -0,0 +1,239 @@ +#coding:utf-8 + +""" +ID: issue-8203 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8203 +TITLE: MAKE_DBKEY can raise 'malformed string' for some table names +DESCRIPTION: + Test verifies ability to create table with random name for each of Unicode ranges + defined in https://jrgraphix.net/r/Unicode/, except following: + (0xD800, 0xDB7F), # High Surrogates + (0xDB80, 0xDBFF), # High Private Use Surrogates + (0xDC00, 0xDFFF), # Low Surrogates + Random name is generated for each range, with random length from scope NAME_MIN_LEN ... NAME_MAX_LEN scope. + Then we create table with such name and stored procedure that attempts to use make_dbkey() with 1st argument + equals to just created table. + This action is repeated REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE times for each Unicode range. + Some characters from 'Basic Latin' are NOT included in any table names - see CHARS_TO_SKIP. + No error must raise for any of checked Unicode scopes. + Example of output when problem does exist: + iter=4 of REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE=5: SUCCESS + range_name='Basic Latin', ..., table_random_unicode_name='}JIry@frnWdzb]5[:A=IomGozwyM*rmJ' + Error while parsing procedure SP_CHK's BLR + -Malformed string + err.gds_codes=(335544876, 335544849) + err.sqlcode=-901 + err.sqlstate='2F000' +NOTES: + [11.08.2024] pzotov + Confirmed bug on 6.0.0.421, 5.0.1.1469 + Checked on 6.0.0.423, 5.0.2.1477 +""" +import pytest +from firebird.qa import * +from io import BytesIO +from firebird.driver import SrvRestoreFlag, DatabaseError +import locale +import random + +db = db_factory() +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +######################### +### s e t t i n g s ### +######################### +CHARS_TO_SKIP = set('<>|"\'^') +NAME_MIN_LEN = 32 +NAME_MAX_LEN = 63 +REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE = 5 # duration: ~60" + +#------------------------------------------------ + +def get_random_unicode(length, bound_points): + # https://stackoverflow.com/questions/1477294/generate-random-utf-8-string-in-python + try: + get_char = unichr + except NameError: + get_char = chr + + alphabet = [ + get_char(code_point) for code_point in range(bound_points[0],bound_points[1]) + ] + return ''.join(random.choice(alphabet) for i in range(length)) + +#------------------------------------------------ + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action, capsys): + + # https://jrgraphix.net/r/Unicode/ + UNICODE_RANGES_MAP = { + (0x0020, 0x007F) : 'Basic Latin', + (0x00A0, 0x00FF) : 'Latin-1 Supplement', + (0x0100, 0x017F) : 'Latin Extended-A', + (0x0180, 0x024F) : 'Latin Extended-B', + (0x0400, 0x04FF) : 'Cyrillic', + (0x0500, 0x052F) : 'Cyrillic Supplementary', + (0x0300, 0x036F) : 'Combining Diacritical Marks', + (0x0250, 0x02AF) : 'IPA Extensions', + (0x0370, 0x03FF) : 'Greek and Coptic', + (0x0530, 0x058F) : 'Armenian', + (0x02B0, 0x02FF) : 'Spacing Modifier Letters', + (0x0590, 0x05FF) : 'Hebrew', + (0x0600, 0x06FF) : 'Arabic', + (0x0700, 0x074F) : 'Syriac', + (0x0780, 0x07BF) : 'Thaana', + (0x0900, 0x097F) : 'Devanagari', + (0x0980, 0x09FF) : 'Bengali', + (0x0A00, 0x0A7F) : 'Gurmukhi', + (0x0A80, 0x0AFF) : 'Gujarati', + (0x0B00, 0x0B7F) : 'Oriya', + (0x0B80, 0x0BFF) : 'Tamil', + (0x0C00, 0x0C7F) : 'Telugu', + (0x0C80, 0x0CFF) : 'Kannada', + (0x0D00, 0x0D7F) : 'Malayalam', + (0x0D80, 0x0DFF) : 'Sinhala', + (0x0E00, 0x0E7F) : 'Thai', + (0x0E80, 0x0EFF) : 'Lao', + (0x0F00, 0x0FFF) : 'Tibetan', + (0x1000, 0x109F) : 'Myanmar', + (0x10A0, 0x10FF) : 'Georgian', + (0x1100, 0x11FF) : 'Hangul Jamo', + (0x1200, 0x137F) : 'Ethiopic', + (0x13A0, 0x13FF) : 'Cherokee', + (0x1400, 0x167F) : 'Unified Canadian Aboriginal Syllabics', + (0x1680, 0x169F) : 'Ogham', + (0x16A0, 0x16FF) : 'Runic', + (0x1700, 0x171F) : 'Tagalog', + (0x1720, 0x173F) : 'Hanunoo', + (0x1740, 0x175F) : 'Buhid', + (0x1760, 0x177F) : 'Tagbanwa', + (0x1780, 0x17FF) : 'Khmer', + (0x1800, 0x18AF) : 'Mongolian', + (0x1900, 0x194F) : 'Limbu', + (0x1950, 0x197F) : 'Tai Le', + (0x19E0, 0x19FF) : 'Khmer Symbols', + (0x1D00, 0x1D7F) : 'Phonetic Extensions', + (0x1E00, 0x1EFF) : 'Latin Extended Additional', + (0x1F00, 0x1FFF) : 'Greek Extended', + (0x2000, 0x206F) : 'General Punctuation', + (0x2070, 0x209F) : 'Superscripts and Subscripts', + (0x20A0, 0x20CF) : 'Currency Symbols', + (0x20D0, 0x20FF) : 'Combining Diacritical Marks for Symbols', + (0x2100, 0x214F) : 'Letterlike Symbols', + (0x2150, 0x218F) : 'Number Forms', + (0x2190, 0x21FF) : 'Arrows', + (0x2200, 0x22FF) : 'Mathematical Operators', + (0x2300, 0x23FF) : 'Miscellaneous Technical', + (0x2400, 0x243F) : 'Control Pictures', + (0x2440, 0x245F) : 'Optical Character Recognition', + (0x2460, 0x24FF) : 'Enclosed Alphanumerics', + (0x2500, 0x257F) : 'Box Drawing', + (0x2580, 0x259F) : 'Block Elements', + (0x25A0, 0x25FF) : 'Geometric Shapes', + (0x2600, 0x26FF) : 'Miscellaneous Symbols', + (0x2700, 0x27BF) : 'Dingbats', + (0x27C0, 0x27EF) : 'Miscellaneous Mathematical Symbols-A', + (0x27F0, 0x27FF) : 'Supplemental Arrows-A', + (0x2800, 0x28FF) : 'Braille Patterns', + (0x2900, 0x297F) : 'Supplemental Arrows-B', + (0x2980, 0x29FF) : 'Miscellaneous Mathematical Symbols-B', + (0x2A00, 0x2AFF) : 'Supplemental Mathematical Operators', + (0x2B00, 0x2BFF) : 'Miscellaneous Symbols and Arrows', + (0x2E80, 0x2EFF) : 'CJK Radicals Supplement', + (0x2F00, 0x2FDF) : 'Kangxi Radicals', + (0x2FF0, 0x2FFF) : 'Ideographic Description Characters', + (0x3000, 0x303F) : 'CJK Symbols and Punctuation', + (0x3040, 0x309F) : 'Hiragana', + (0x30A0, 0x30FF) : 'Katakana', + (0x3100, 0x312F) : 'Bopomofo', + (0x3130, 0x318F) : 'Hangul Compatibility Jamo', + (0x3190, 0x319F) : 'Kanbun', + (0x31A0, 0x31BF) : 'Bopomofo Extended', + (0x31F0, 0x31FF) : 'Katakana Phonetic Extensions', + (0x3200, 0x32FF) : 'Enclosed CJK Letters and Months', + (0x3300, 0x33FF) : 'CJK Compatibility', + (0x3400, 0x4DBF) : 'CJK Unified Ideographs Extension A', + (0x4DC0, 0x4DFF) : 'Yijing Hexagram Symbols', + (0x4E00, 0x9FFF) : 'CJK Unified Ideographs', + (0xA000, 0xA48F) : 'Yi Syllables', + (0xA490, 0xA4CF) : 'Yi Radicals', + (0xAC00, 0xD7AF) : 'Hangul Syllables', + (0xE000, 0xF8FF) : 'Private Use Area', + (0xF900, 0xFAFF) : 'CJK Compatibility Ideographs', + (0xFB00, 0xFB4F) : 'Alphabetic Presentation Forms', + (0xFB50, 0xFDFF) : 'Arabic Presentation Forms-A', + (0xFE00, 0xFE0F) : 'Variation Selectors', + (0xFE20, 0xFE2F) : 'Combining Half Marks', + (0xFE30, 0xFE4F) : 'CJK Compatibility Forms', + (0xFE50, 0xFE6F) : 'Small Form Variants', + (0xFE70, 0xFEFF) : 'Arabic Presentation Forms-B', + (0xFF00, 0xFFEF) : 'Halfwidth and Fullwidth Forms', + (0xFFF0, 0xFFFF) : 'Specials', + (0x10000, 0x1007F) : 'Linear B Syllabary', + (0x10080, 0x100FF) : 'Linear B Ideograms', + (0x10100, 0x1013F) : 'Aegean Numbers', + (0x10300, 0x1032F) : 'Old Italic', + (0x10330, 0x1034F) : 'Gothic', + (0x10380, 0x1039F) : 'Ugaritic', + (0x10400, 0x1044F) : 'Deseret', + (0x10450, 0x1047F) : 'Shavian', + (0x10480, 0x104AF) : 'Osmanya', + (0x10800, 0x1083F) : 'Cypriot Syllabary', + (0x1D000, 0x1D0FF) : 'Byzantine Musical Symbols', + (0x1D100, 0x1D1FF) : 'Musical Symbols', + (0x1D300, 0x1D35F) : 'Tai Xuan Jing Symbols', + (0x1D400, 0x1D7FF) : 'Mathematical Alphanumeric Symbols', + (0x20000, 0x2A6DF) : 'CJK Unified Ideographs Extension B', + (0x2F800, 0x2FA1F) : 'CJK Compatibility Ideographs Supplement', + (0xE0000, 0xE007F) : 'Tags', + } + + for bound_points, range_name in UNICODE_RANGES_MAP.items(): + + for iter in range(1,REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE+1): + + + table_random_unicode_name = get_random_unicode( random.randint(NAME_MIN_LEN, NAME_MAX_LEN), bound_points ) + table_random_unicode_name = ''.join(c for c in table_random_unicode_name if c not in CHARS_TO_SKIP) + + test_sql = f""" + recreate table "{table_random_unicode_name.replace('"','""')}"(id int) + ^ + create or alter procedure sp_chk as + declare id1 int; + begin + select /* {range_name=} {iter=} */ id from "{table_random_unicode_name.replace('"','""')}" where rdb$db_key = make_dbkey('{table_random_unicode_name}', 0) into id1; + end + ^ + """ + # select id from "{table_random_unicode_name.replace('"','""')}" where rdb$db_key = make_dbkey('{table_random_unicode_name.replace("'","''")}', 0) into id1; + + expected_txt = f'{iter=} of {REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE=}: SUCCESS' + with act.db.connect(charset = 'utf-8') as con: + try: + for line in test_sql.split('^'): + if (expr := line.strip()): + if expr != '^': + con.execute_immediate(expr) + else: + con.commit() + con.commit() + print(expected_txt) + except DatabaseError as err: + print(f'{range_name=}, {iter=} of {REPEAT_CHECKS_FOR_SELECTED_UNICODE_RANGE=}, {table_random_unicode_name=}') + print(err) + print(f'{err.gds_codes=}') + print(f'{err.sqlcode=}') + print(f'{err.sqlstate=}') + ''' + backup = BytesIO() + with act.connect_server() as srv: + srv.database.local_backup(database=act.db.db_path, backup_stream=backup) + backup.seek(0) + srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags = SrvRestoreFlag.REPLACE) + ''' + act.expected_stdout = expected_txt + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From ec8f44b9897bdb0e2866e2661d57f791c144430c Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Sun, 11 Aug 2024 11:13:42 -0300 Subject: [PATCH 0124/1064] Do not run encryption tests in docker. --- docker/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/run.sh b/docker/run.sh index 10c687fd..ce0d7970 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -21,5 +21,5 @@ pytest \ --md-report-output /qa-out/md_report.md \ --ignore=tests/functional/replication \ --ignore=tests/functional/basic/isql/test_08.py \ - -m "not replication" \ + -m "not replication and not encryption" \ "$@" From 1d19a27575b4622bf60136cde6edbb54bd31b179 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 Aug 2024 09:42:14 +0300 Subject: [PATCH 0125/1064] Added alias 'tmp_fd0fa8a3_alias' for upcoming test --- files/qa-databases.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index 8ef4f321..5681f655 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -262,6 +262,13 @@ tmp_gh_8194_alias = $(dir_sampleDb)/qa/tmp_gh_8194.fdb DefaultDbCachePages = 128 } +# https://github.com/FirebirdSQL/firebird/commit/fd0fa8a3a58fbfe7fdc0641b4e48258643d72127 +# Let include file name into error message when creation of temp file failed +tmp_fd0fa8a3_alias = $(dir_sampleDb)/qa/tmp_fd0fa8a3.fdb +{ + TempTableDirectory = <> +} + # Databases for replication tests: # From a3639776965424785fce43a348bbf684f3824b60 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 Aug 2024 09:58:06 +0300 Subject: [PATCH 0126/1064] Added/Updated tests\functional\tabloid\test_fd0fa8a3.py: Checked on Windows/Linux, 6.0.0.423, 5.0.2.1477, 4.0.6.3141. --- tests/functional/tabloid/test_fd0fa8a3.py | 137 ++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/functional/tabloid/test_fd0fa8a3.py diff --git a/tests/functional/tabloid/test_fd0fa8a3.py b/tests/functional/tabloid/test_fd0fa8a3.py new file mode 100644 index 00000000..d3a6768e --- /dev/null +++ b/tests/functional/tabloid/test_fd0fa8a3.py @@ -0,0 +1,137 @@ +#coding:utf-8 + +""" +ID: None +ISSUE: https://github.com/FirebirdSQL/firebird/commit/fd0fa8a3a58fbfe7fdc0641b4e48258643d72127 +TITLE: Let include file name into error message when creation of temp file failed. +DESCRIPTION: + Test uses pre-created databases.conf which has alias 'tmp_fd0fa8a3_alias' (see variable REQUIRED_ALIAS). + Database file for that alias must NOT exist in the $(dir_sampleDb)/qa/ subdirectory: it will be created here. + For this alias parameter TempTableDirectory is defined and it points to invalid/inaccessible directory. + Currently its value is: '<>' (without single quotes), so there is no way to create any file in it. + We check that: + * client still has ability to create GTT and put data in it, without getting error; + * firebird.log will have appropriate message about problem with creating file ('fb_*****') in TempTableDirectory +NOTES: + [12.08.2024] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + 3. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + 4. Invalid value of TempTableDirectory causes appropriate message to appear in firebird.log TWO times: first when QA-plugin prepares + test database (and this is out of scope to be checked by this test), and second when we try to insert data in the GTT. + DDL statement ('create global temporary table') does NOT cause any message in firebird.log until we do not try to add data in it. + Because of that, difference between content of firebird.log will contain only ONE message "Error creating file...". + + Parameter 'TempTableDirectory' exists in FB-4.x since 20.04.2021, commit f2805020a6f34d253c93b8edac6068c1b35f9b89., build 4.0.0.2436. + Checked on Windows/Linux, 6.0.0.423, 5.0.2.1477, 4.0.6.3141. +""" + +import os +import re +import locale +from difflib import unified_diff +from pathlib import Path + +import pytest +from firebird.qa import * + +REQUIRED_ALIAS = 'tmp_fd0fa8a3_alias' + +substitutions = [ ('[ \t]+', ' ') + ,('Error creating file in TempTableDirectory.*', 'Error creating file in TempTableDirectory') + ,('I/O error during "((CreateFile\\s+\\(create\\))|open)" operation for file.*', 'I/O error during CreateFile operation for file') + ] +db = db_factory(filename = '#' + REQUIRED_ALIAS) +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_NNNN_alias = $(dir_sampleDb)/qa/tmp_qa_NNNN.fdb + # - then we extract filename: 'tmp_qa_NNNN.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + check_sql = f""" + set bail on; + recreate global temporary table test(x int); + set count on; + insert into test(x) values(1); + """ + + # Check-1: no error must be issued on client-side, all records have to be inserted: + # + expected_stdout = f""" + Records affected: 1 + """ + + # Get content of firebird.log BEFORE test. + # ::: NB ::: + # At this point firebird.log must already contain message about unable to create file because of inaccessible TempTableDirectory value. + # This message was added when test database have been created by QA-plugin, i.e. out of this test code. So, the difference between + # log content will NOT contain this message! + # + log_before = act.get_firebird_log() + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], input = check_sql, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # Get content of firebird.log AFTER test. + # ONLY ONE message about invalid TempTableDirectory value will be taken in account! + # + log_after = act.get_firebird_log() + + #---------------------------------------------------- + + # Check-2: firebird.log must have message (partially localized): + # on Windows: + # Database: ... + # Error creating file in TempTableDirectory "..." + # I/O error during "CreateFile (create)" operation for file "..." + # Error while trying to create file + # Syntax error in file name, folder name, or volume label [ NB: THIS LINE CAN BE LOCALIZED ] + # + # on LINUX: + # Database: ... + # Error creating file in TempTableDirectory "..." + # I/O error during "open" operation for file "..." + # Error while trying to create file + # No such file or directory + + allowed_patterns = [ re.compile('Error creating file in TempTableDirectory',re.IGNORECASE), + re.compile('I/O error during "((CreateFile\\s+\\(create\\))|open)" operation for file',re.IGNORECASE), + re.compile('Error while trying to create file',re.IGNORECASE) + ] + + for line in unified_diff(log_before, log_after): + if (msg := line.strip()): + if msg.startswith('+') and act.match_any(msg, allowed_patterns): + print(msg[1:]) + + act.expected_stdout = """ + Error creating file in TempTableDirectory + I/O error during "CreateFile (create)" operation for file + Error while trying to create file + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 4d3822464ddbeb4d71915e510efe7438d9613d89 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 Aug 2024 10:04:10 +0300 Subject: [PATCH 0127/1064] Added/Updated tests\bugs\core_6487_test.py: minor adjustment --- tests/bugs/core_6487_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/bugs/core_6487_test.py b/tests/bugs/core_6487_test.py index 68156a0f..38a51bb8 100644 --- a/tests/bugs/core_6487_test.py +++ b/tests/bugs/core_6487_test.py @@ -3,8 +3,7 @@ """ ID: issue-6717 ISSUE: 6717 -TITLE: FETCH ABSOLUTE and RELATIVE beyond bounds of cursor should always position - immediately before-first or after-last +TITLE: FETCH ABSOLUTE and RELATIVE beyond bounds of cursor should always position immediately before-first or after-last DESCRIPTION: JIRA: CORE-6487 FBTEST: bugs.core_6487 From 980cf2950e0e0e0ccd60d0ab93feb54e41123fb8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 Aug 2024 14:47:01 +0300 Subject: [PATCH 0128/1064] Added/Updated tests\functional\tabloid\test_80fd0682.py: Checked on 4.0.0.2372. Checked on 6.0.0.423, 5.0.2.1477. --- tests/functional/tabloid/test_80fd0682.py | 179 ++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 tests/functional/tabloid/test_80fd0682.py diff --git a/tests/functional/tabloid/test_80fd0682.py b/tests/functional/tabloid/test_80fd0682.py new file mode 100644 index 00000000..352c63b4 --- /dev/null +++ b/tests/functional/tabloid/test_80fd0682.py @@ -0,0 +1,179 @@ +#coding:utf-8 + +""" +ID: None +ISSUE: https://github.com/FirebirdSQL/firebird/commit/80fd06828e72f9e8335150c923350730013b3b28 +TITLE: Fixed bug with index names patterns in online validation service +DESCRIPTION: + Sources to read (19-feb-2021): + https://sourceforge.net/p/firebird/mailman/message/37222898/ + https://sourceforge.net/p/firebird/mailman/message/37223338/ + (Firebird-devel Digest, Vol 178, Issue 34; Vol 178, Issue 35) +NOTES: + Confirmed bug on 4.0.0.2369. + Checked on 4.0.0.2372 -- all fine. + Checked on 6.0.0.423, 5.0.2.1477. +""" + +import re +import pytest +from firebird.qa import * + +init_sql = """ + create table a(id int); + create index a on a(id); + create table b(id int); + create index x on b(id); + create table c(id int); + create index c on c(id); + commit; +""" +db = db_factory(init = init_sql) + +substitutions = [ ('[ \t]+', ' ') + ] +act = python_act('db', substitutions = substitutions) + +#------------------------------------------------------------- + +def clean_text(line: str): + # Used to remove timestamp from the beginning of line, + # then remove ID of relation / index.: + line = re.sub(r'^\d{2}:\d{2}:\d{2}.\d{2,3}\s+', '', line) + line = re.sub('Relation \\d+ \\(', 'Relation (', line) + line = re.sub('Index \\d+ \\(', 'Index (', line) + return line + +#------------------------------------------------------------- + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + validation_log = [] + # Run online database validation: + with act.connect_server() as srv: + for ix_key in ('incl', 'excl'): + for tab_name in ('A', 'B'): + if ix_key == 'incl': + srv.database.validate(database=act.db.db_path, include_table = tab_name.upper()) + else: + srv.database.validate(database=act.db.db_path, exclude_table = tab_name.upper()) + validation_log.append(f'{ix_key=}, {tab_name=}') + validation_log.extend( [clean_text(line) for line in srv.readlines()] ) + for idx_name in ('A', 'X'): + if ix_key == 'incl': + srv.database.validate(database=act.db.db_path, include_index = idx_name.upper()) + else: + srv.database.validate(database=act.db.db_path, exclude_index = idx_name.upper()) + validation_log.append(f'{ix_key=}, {idx_name=}') + validation_log.extend( [clean_text(line) for line in srv.readlines()] ) + # validation_log.extend( [ re.sub('Index \\d+ \\(', 'Index (', re.sub(r'^\d{2}:\d{2}:\d{2}.\d{2,3}\s+', '', line)) for line in srv.readlines() ] ) + #for line in srv.readlines(): + # validation_log.append( clean_text(line) ) + + + for line in validation_log: + print(line) + + act.expected_stdout = """ + ix_key='incl', tab_name='A' + Validation started + Relation (A) + process pointer page 0 of 1 + Index (A) + Relation (A) is ok + Validation finished + + ix_key='incl', tab_name='B' + Validation started + Relation (B) + process pointer page 0 of 1 + Index (X) + Relation (B) is ok + Validation finished + + ix_key='incl', idx_name='A' + Validation started + Relation (A) + process pointer page 0 of 1 + Index (A) + Relation (A) is ok + Relation (B) + process pointer page 0 of 1 + Relation (B) is ok + Relation (C) + process pointer page 0 of 1 + Relation (C) is ok + Validation finished + + ix_key='incl', idx_name='X' + Validation started + Relation (A) + process pointer page 0 of 1 + Relation (A) is ok + Relation (B) + process pointer page 0 of 1 + Index (X) + Relation (B) is ok + Relation (C) + process pointer page 0 of 1 + Relation (C) is ok + Validation finished + + ix_key='excl', tab_name='A' + Validation started + Relation (B) + process pointer page 0 of 1 + Index (X) + Relation (B) is ok + Relation (C) + process pointer page 0 of 1 + Index (C) + Relation (C) is ok + Validation finished + + ix_key='excl', tab_name='B' + Validation started + Relation (A) + process pointer page 0 of 1 + Index (A) + Relation (A) is ok + Relation (C) + process pointer page 0 of 1 + Index (C) + Relation (C) is ok + Validation finished + + ix_key='excl', idx_name='A' + Validation started + Relation (A) + process pointer page 0 of 1 + Relation (A) is ok + Relation (B) + process pointer page 0 of 1 + Index (X) + Relation (B) is ok + Relation (C) + process pointer page 0 of 1 + Index (C) + Relation (C) is ok + Validation finished + + ix_key='excl', idx_name='X' + Validation started + Relation (A) + process pointer page 0 of 1 + Index (A) + Relation (A) is ok + Relation (B) + process pointer page 0 of 1 + Relation (B) is ok + Relation (C) + process pointer page 0 of 1 + Index (C) + Relation (C) is ok + Validation finished + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From be6cd50fccfcf95c8c1cd01966ae2cdefbab2973 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 14 Aug 2024 12:14:05 +0300 Subject: [PATCH 0129/1064] Added/Updated tests\bugs\gh_7767_test.py: Checked on 6.0.0.436, 5.0.2.1478, 4.0.6.3142 (all SS/CS; both Windows and Linux). --- tests/bugs/gh_7767_test.py | 171 +++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 tests/bugs/gh_7767_test.py diff --git a/tests/bugs/gh_7767_test.py b/tests/bugs/gh_7767_test.py new file mode 100644 index 00000000..817f750c --- /dev/null +++ b/tests/bugs/gh_7767_test.py @@ -0,0 +1,171 @@ +#coding:utf-8 + +""" +ID: issue-7767 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7767 +TITLE: Slow drop trigger command execution under FB5.0 +DESCRIPTION: + The issued problem can NOT be stably reproduced if we compare time ratio between 'DROP TRIGGER' vs 'DROP PROCEDURE' statements. + ratio between execution time differed for too small value (e.g. 7.2 before fix and 6.9 after it). + + But regression can be noted if we check ratio between CPU time spent for 'DROP TRIGGER' and some code that does not relate + to any DB operations and makes some evaluation. Such code can be single call to CRYPT_HASH function (doing in loop many times). + This function must be called EVAL_CRYPT_HASH_COUNT times. + Result of evaluating of CRYPT_HASH is stored in var. 'eval_crypt_hash_time' and serves further as "etalone" value. + + Test database is initialized by creation of PSQL_OBJECTS_COUNT triggers and is copied to backup FDB (see 'tmp_fdb'). + Then we call 'DROP TRIGGER' using 'for select ... from rdb$triggers' cursor (so their count is also PSQL_OBJECTS_COUNT). + We repeat this in loop for MEASURES_COUNT iterations, doing restore from DB copy before every iteration (copy 'tmp_fdb' to act.db). + Median of ratios between CPU times obtained in this loop and eval_crypt_hash_time must be less than MAX_RATIO. + Duration is measured as difference between psutil.Process(fb_pid).cpu_times() counters. +NOTES: + [14.08.2024] pzotov + Problem did exist in FB 5.x until commit "Fix #7759 - Routine calling overhead increased by factor 6 vs Firebird 4.0.0." + https://github.com/FirebirdSQL/firebird/commit/d621ffbe0cf2d43e13480628992180c28a5044fe (03-oct-2023 13:32). + Before this commit (up to 5.0.0.1236) median of ratios was more than 6.5. + After fix it was reduced to ~3.5 ... 4.0 (5.0.0.1237 and above). + This ratio seems to be same on Windows and Linux. + + Built-in function CRYPT_HASH appeared in 4.0.0.2180, 27-aug-2020, commit: + https://github.com/FirebirdSQL/firebird/commit/e9f3eb360db41ddff27fa419b908876be0d2daa5 + ("Moved cryptographic hashes to separate function crypt_hash(), crc32 - into function hash()") + + Test duration time: about 50s. + Checked on 6.0.0.436, 5.0.2.1478, 4.0.6.3142 (all SS/CS; both Windows and Linux). +""" +import shutil +from pathlib import Path +import psutil +import pytest +from firebird.qa import * +import time + +########################### +### S E T T I N G S ### +########################### + +# How many times to generate crypt_hash: +EVAL_CRYPT_HASH_COUNT=5000 + +# How many times we call procedures: +MEASURES_COUNT = 11 + +# How many procedures and triggers must be created: +PSQL_OBJECTS_COUNT = 500 + +# Maximal value for ratio between maximal and minimal medians +# +MAX_RATIO = 6 +############# + +init_sql = """ + set bail on; + alter database set linger to 0; + create sequence g; + create table test(id int); + commit; + set term ^; +""" +init_sql = '\n'.join( + ( init_sql + ,'\n'.join( [ f'create trigger tg_{i} for test before insert as declare v int; begin v = gen_id(g,1); end ^' for i in range(PSQL_OBJECTS_COUNT) ] ) + ,'^ set term ;^' + ,'commit;' + ) + ) + +db = db_factory(init = init_sql) +act = python_act('db') + +tmp_fdb = temp_file('tmp_gh_7767_copy.tmp') + +expected_stdout = """ + Medians ratio: acceptable +""" + +eval_crypt_code = f""" + execute block as + declare v_hash varbinary(64); + declare n int = {EVAL_CRYPT_HASH_COUNT}; + begin + while (n > 0) do begin + v_hash = crypt_hash(lpad('', 32765, uuid_to_char(gen_uuid())) using SHA512); + n = n - 1; + end + end +""" + +drop_trg_code = """ + execute block as + declare trg_drop type of column rdb$triggers.rdb$trigger_name; + begin + for select 'DROP TRIGGER '||trim(rdb$trigger_name) + from rdb$triggers + where rdb$system_flag=0 + into :trg_drop do + begin + in autonomous transaction do + begin + execute statement :trg_drop; + end + end + end +""" + +#-------------------------------------------------------------------- +def median(lst): + n = len(lst) + s = sorted(lst) + return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None + +#-------------------------------------------------------------------- + +def get_server_pid(con): + with con.cursor() as cur: + cur.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur.fetchone()[0]) + return fb_pid + +#-------------------------------------------------------------------- + +@pytest.mark.version('>=4.0.0') +def test_1(act: Action, tmp_fdb: Path, capsys): + + shutil.copy2(act.db.db_path, tmp_fdb) + + with act.db.connect() as con: + fb_pid = get_server_pid(con) + fb_info_init = psutil.Process(fb_pid).cpu_times() + con.execute_immediate( eval_crypt_code ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + eval_crypt_hash_time = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + ddl_time = {} + for iter in range(MEASURES_COUNT): + + with act.db.connect() as con: + fb_pid = get_server_pid(con) + fb_info_init = psutil.Process(fb_pid).cpu_times() + con.execute_immediate( drop_trg_code ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + ddl_time[ 'tg', iter ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + # Quick jump back to database with PSQL_OBJECTS_COUNT triggers that we made on init phase: + shutil.copy2(tmp_fdb, act.db.db_path) + + ratios = [ ddl_time['tg',iter] / eval_crypt_hash_time for iter in range(MEASURES_COUNT) ] + median_ratio = median(ratios) + + SUCCESS_MSG = 'Medians ratio: acceptable' + if median_ratio < MAX_RATIO: + print(SUCCESS_MSG) + else: + print( 'Medians ratio: /* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:.2f}'.format(median_ratio), '{:.2f}'.format(MAX_RATIO) ) ) + print('ratios:',['{:.2f}'.format(r) for r in ratios]) + print('CPU times:') + for k,v in ddl_time.items(): + print(k,':::','{:.2f}'.format(v)) + + act.expected_stdout = SUCCESS_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 572c7c78b07d6f5d36b6af3d2e960ce5b72544b9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 Aug 2024 13:23:14 +0300 Subject: [PATCH 0130/1064] Added/Updated tests\bugs\gh_5978_test.py: minor change in comments --- tests/bugs/gh_5978_test.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/bugs/gh_5978_test.py b/tests/bugs/gh_5978_test.py index 6bdba7a3..c443c4ca 100644 --- a/tests/bugs/gh_5978_test.py +++ b/tests/bugs/gh_5978_test.py @@ -5,21 +5,33 @@ ISSUE: https://github.com/FirebirdSQL/firebird/issues/5978 TITLE: Access to the name of DB encryption key [CORE5712] DESCRIPTION: - Test creates temporary user with system privilege GET_DBCRYPT_INFO in order to allow him to obtain encryption info. - Then we run following: - 1) encrypt DB using plugin 'fbSampleDbCrypt' provided in every FB 4.x+ snapshot; - 2) make connection as SYSDBA and ask DB-crypt info (DbInfoCode.CRYPT_PLUGIN and DbInfoCode.CRYPT_KEY) - 3) decrypt DB - After this we repeat these actions, except that in "2)" we use temporary user ('tmp_senior') instead of SYSDBA - (he must get same info as was obtained in previous step for SYSDBA). + Test uses Firebird built-in encryption plugin wich actually does encryption using trivial algorithm. + Before running this test following prerequisites must be met: + 1. Files fbSampleKeyHolder.conf, fbSampleKeyHolder.dll, fbSampleDbCrypt.conf and fbSampleDbCrypt.dll + must be copied from $FB_HOME/examples/prebuilt/plugins/ to $FB_HOME/plugins/ + (on Linux name of binaries are: libfbSampleDbCrypt.so and libfbSampleKeyHolder.so) + 2. File fbSampleKeyHolder.conf must contain lines: Auto = true and KeyRed = + 3. File $QA_HOME/pytest.ini must contain line with 'encryption' marker declaration. + + We create temporary user with system privilege GET_DBCRYPT_INFO in order to allow him to obtain encryption info. + Then we run following: + 1) encrypt DB using plugin 'fbSampleDbCrypt' provided in every FB 4.x+ snapshot; + 2) make connection as SYSDBA and ask DB-crypt info (DbInfoCode.CRYPT_PLUGIN and DbInfoCode.CRYPT_KEY) + 3) decrypt DB + After this we repeat these actions, except that in "2)" we use temporary user ('tmp_senior') instead of SYSDBA + (he must get same info as was obtained in previous step for SYSDBA). NOTES: - [08.05.2024] pzotov + [08.05.2024] pzotov - ### ACHTUNG ### TEST REQUIRES FIREBIRD-DRIVER VERSION 1.10.4+ (date: 07-may-2024). - See reply from pcisar, letters with subj: "fb_info_crypt_key: how it can be obtained using firebird-driver ? // GH-5978, 2018" + ### ACHTUNG ### TEST REQUIRES FIREBIRD-DRIVER VERSION 1.10.4+ (date: 07-may-2024). + Thanks to pcisar for explanation of DbInfoCode usage. + See letters with subj "fb_info_crypt_key: how it can be obtained using firebird-driver ? // GH-5978, 2018" (27.04.2024 14:55). - Checked on 4.0.5.3092, 5.0.1.1395, 6.0.0.346. - FB 3.x is not checked. + Firebird 3.x can not be checked. Exception: + raise NotSupportedError(f"Info code {info_code} not supported by engine version {self.__engine_version}") + firebird.driver.types.NotSupportedError: Info code 138 not supported by engine version 3.0 + + Checked on 4.0.5.3092, 5.0.1.1395, 6.0.0.346. """ import os import locale From 2333bc1db1173fc3533b1448735cddb557955913 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 Aug 2024 22:03:24 +0300 Subject: [PATCH 0131/1064] Added/Updated tests\bugs\gh_6545_test.py: Checked on 4.0.0.436, 5.0.2.1478, 4.0.6.3142. NOTE: TEST REQUIRES FIREBIRD-DRIVER VERSION 1.10.6+ --- tests/bugs/gh_6545_test.py | 689 +++++++++++++++++++++++++++++++++++++ 1 file changed, 689 insertions(+) create mode 100644 tests/bugs/gh_6545_test.py diff --git a/tests/bugs/gh_6545_test.py b/tests/bugs/gh_6545_test.py new file mode 100644 index 00000000..89bab2b5 --- /dev/null +++ b/tests/bugs/gh_6545_test.py @@ -0,0 +1,689 @@ +#coding:utf-8 + +""" +ID: issue-6545 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6545 +TITLE: Error writing to TIMESTAMP/TIME WITH TIME ZONE array +DESCRIPTION: + Test generates values which will be inserted into ARRAY columns defined as 'time with time zone' and 'timestamp with time zone'. + We process time zones defined in the FB_HOME/include/firebird/TimeZones.h (except several, see notes below), + and use every time zone value as argument to 'get_timezone()' in datetime.dsatetime / datetime.time calls. + Then we run DML which tries to insert tuple of generated data into appropriate ARRAY columns. This must not raise error. + Finally, we run query to get just inserted data and compare its result with input argument that was used in previous step. +NOTES: + [15.08.2024] pzotov + 1. ### ACHTUNG ### TEST REQUIRES FIREBIRD-DRIVER VERSION 1.10.6+ (date: 15-aug-2024). + See also addition in firebird-driver doc: + https://firebird-driver.readthedocs.io/en/latest/usage-guide.html#working-with-time-timestamp-with-timezone + + 2. Following timezones present in $FB_HOME/include/firebird/TimeZones.h + and in https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + but are absent in pytz.all_timezones list: + America/Ciudad_Juarez + Europe/Kyiv + Pacific/Kanton + We have to SKIP them from handling. + + Checked on 4.0.0.436, 5.0.2.1478, 4.0.6.3142 +""" +import datetime +from firebird.driver import get_timezone +import random + +import pytest +from firebird.qa import * + +init_script = """ + create table test ( + arr_tmtz time with time zone [0:2] + ,arr_tstz timestamp with time zone [0:2] + ); +""" +db = db_factory(init = init_script) + +act = python_act('db') + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + fb_time_zones = [ + 'Africa/Abidjan' + ,'Africa/Accra' + ,'Africa/Addis_Ababa' + ,'Africa/Algiers' + ,'Africa/Asmara' + ,'Africa/Asmera' + ,'Africa/Bamako' + ,'Africa/Bangui' + ,'Africa/Banjul' + ,'Africa/Bissau' + ,'Africa/Blantyre' + ,'Africa/Brazzaville' + ,'Africa/Bujumbura' + ,'Africa/Cairo' + ,'Africa/Casablanca' + ,'Africa/Ceuta' + ,'Africa/Conakry' + ,'Africa/Dakar' + ,'Africa/Dar_es_Salaam' + ,'Africa/Djibouti' + ,'Africa/Douala' + ,'Africa/El_Aaiun' + ,'Africa/Freetown' + ,'Africa/Gaborone' + ,'Africa/Harare' + ,'Africa/Johannesburg' + ,'Africa/Juba' + ,'Africa/Kampala' + ,'Africa/Khartoum' + ,'Africa/Kigali' + ,'Africa/Kinshasa' + ,'Africa/Lagos' + ,'Africa/Libreville' + ,'Africa/Lome' + ,'Africa/Luanda' + ,'Africa/Lubumbashi' + ,'Africa/Lusaka' + ,'Africa/Malabo' + ,'Africa/Maputo' + ,'Africa/Maseru' + ,'Africa/Mbabane' + ,'Africa/Mogadishu' + ,'Africa/Monrovia' + ,'Africa/Nairobi' + ,'Africa/Ndjamena' + ,'Africa/Niamey' + ,'Africa/Nouakchott' + ,'Africa/Ouagadougou' + ,'Africa/Porto-Novo' + ,'Africa/Sao_Tome' + ,'Africa/Timbuktu' + ,'Africa/Tripoli' + ,'Africa/Tunis' + ,'Africa/Windhoek' + ,'America/Adak' + ,'America/Anchorage' + ,'America/Anguilla' + ,'America/Antigua' + ,'America/Araguaina' + ,'America/Argentina/Buenos_Aires' + ,'America/Argentina/Catamarca' + ,'America/Argentina/ComodRivadavia' + ,'America/Argentina/Cordoba' + ,'America/Argentina/Jujuy' + ,'America/Argentina/La_Rioja' + ,'America/Argentina/Mendoza' + ,'America/Argentina/Rio_Gallegos' + ,'America/Argentina/Salta' + ,'America/Argentina/San_Juan' + ,'America/Argentina/San_Luis' + ,'America/Argentina/Tucuman' + ,'America/Argentina/Ushuaia' + ,'America/Aruba' + ,'America/Asuncion' + ,'America/Atikokan' + ,'America/Atka' + ,'America/Bahia' + ,'America/Bahia_Banderas' + ,'America/Barbados' + ,'America/Belem' + ,'America/Belize' + ,'America/Blanc-Sablon' + ,'America/Boa_Vista' + ,'America/Bogota' + ,'America/Boise' + ,'America/Buenos_Aires' + ,'America/Cambridge_Bay' + ,'America/Campo_Grande' + ,'America/Cancun' + ,'America/Caracas' + ,'America/Catamarca' + ,'America/Cayenne' + ,'America/Cayman' + ,'America/Chicago' + ,'America/Chihuahua' + # -- !! -- ,'America/Ciudad_Juarez' + ,'America/Coral_Harbour' + ,'America/Cordoba' + ,'America/Costa_Rica' + ,'America/Creston' + ,'America/Cuiaba' + ,'America/Curacao' + ,'America/Danmarkshavn' + ,'America/Dawson' + ,'America/Dawson_Creek' + ,'America/Denver' + ,'America/Detroit' + ,'America/Dominica' + ,'America/Edmonton' + ,'America/Eirunepe' + ,'America/El_Salvador' + ,'America/Ensenada' + ,'America/Fort_Nelson' + ,'America/Fort_Wayne' + ,'America/Fortaleza' + ,'America/Glace_Bay' + ,'America/Godthab' + ,'America/Goose_Bay' + ,'America/Grand_Turk' + ,'America/Grenada' + ,'America/Guadeloupe' + ,'America/Guatemala' + ,'America/Guayaquil' + ,'America/Guyana' + ,'America/Halifax' + ,'America/Havana' + ,'America/Hermosillo' + ,'America/Indiana/Indianapolis' + ,'America/Indiana/Knox' + ,'America/Indiana/Marengo' + ,'America/Indiana/Petersburg' + ,'America/Indiana/Tell_City' + ,'America/Indiana/Vevay' + ,'America/Indiana/Vincennes' + ,'America/Indiana/Winamac' + ,'America/Indianapolis' + ,'America/Inuvik' + ,'America/Iqaluit' + ,'America/Jamaica' + ,'America/Jujuy' + ,'America/Juneau' + ,'America/Kentucky/Louisville' + ,'America/Kentucky/Monticello' + ,'America/Knox_IN' + ,'America/Kralendijk' + ,'America/La_Paz' + ,'America/Lima' + ,'America/Los_Angeles' + ,'America/Louisville' + ,'America/Lower_Princes' + ,'America/Maceio' + ,'America/Managua' + ,'America/Manaus' + ,'America/Marigot' + ,'America/Martinique' + ,'America/Matamoros' + ,'America/Mazatlan' + ,'America/Mendoza' + ,'America/Menominee' + ,'America/Merida' + ,'America/Metlakatla' + ,'America/Mexico_City' + ,'America/Miquelon' + ,'America/Moncton' + ,'America/Monterrey' + ,'America/Montevideo' + ,'America/Montreal' + ,'America/Montserrat' + ,'America/Nassau' + ,'America/New_York' + ,'America/Nipigon' + ,'America/Nome' + ,'America/Noronha' + ,'America/North_Dakota/Beulah' + ,'America/North_Dakota/Center' + ,'America/North_Dakota/New_Salem' + ,'America/Nuuk' + ,'America/Ojinaga' + ,'America/Panama' + ,'America/Pangnirtung' + ,'America/Paramaribo' + ,'America/Phoenix' + ,'America/Port-au-Prince' + ,'America/Port_of_Spain' + ,'America/Porto_Acre' + ,'America/Porto_Velho' + ,'America/Puerto_Rico' + ,'America/Punta_Arenas' + ,'America/Rainy_River' + ,'America/Rankin_Inlet' + ,'America/Recife' + ,'America/Regina' + ,'America/Resolute' + ,'America/Rio_Branco' + ,'America/Rosario' + ,'America/Santa_Isabel' + ,'America/Santarem' + ,'America/Santiago' + ,'America/Santo_Domingo' + ,'America/Sao_Paulo' + ,'America/Scoresbysund' + ,'America/Shiprock' + ,'America/Sitka' + ,'America/St_Barthelemy' + ,'America/St_Johns' + ,'America/St_Kitts' + ,'America/St_Lucia' + ,'America/St_Thomas' + ,'America/St_Vincent' + ,'America/Swift_Current' + ,'America/Tegucigalpa' + ,'America/Thule' + ,'America/Thunder_Bay' + ,'America/Tijuana' + ,'America/Toronto' + ,'America/Tortola' + ,'America/Vancouver' + ,'America/Virgin' + ,'America/Whitehorse' + ,'America/Winnipeg' + ,'America/Yakutat' + ,'America/Yellowknife' + ,'Antarctica/Casey' + ,'Antarctica/Davis' + ,'Antarctica/DumontDUrville' + ,'Antarctica/Macquarie' + ,'Antarctica/Mawson' + ,'Antarctica/McMurdo' + ,'Antarctica/Palmer' + ,'Antarctica/Rothera' + ,'Antarctica/South_Pole' + ,'Antarctica/Syowa' + ,'Antarctica/Troll' + ,'Antarctica/Vostok' + ,'Arctic/Longyearbyen' + ,'Asia/Aden' + ,'Asia/Almaty' + ,'Asia/Amman' + ,'Asia/Anadyr' + ,'Asia/Aqtau' + ,'Asia/Aqtobe' + ,'Asia/Ashgabat' + ,'Asia/Ashkhabad' + ,'Asia/Atyrau' + ,'Asia/Baghdad' + ,'Asia/Bahrain' + ,'Asia/Baku' + ,'Asia/Bangkok' + ,'Asia/Barnaul' + ,'Asia/Beirut' + ,'Asia/Bishkek' + ,'Asia/Brunei' + ,'Asia/Calcutta' + ,'Asia/Chita' + ,'Asia/Choibalsan' + ,'Asia/Chongqing' + ,'Asia/Chungking' + ,'Asia/Colombo' + ,'Asia/Dacca' + ,'Asia/Damascus' + ,'Asia/Dhaka' + ,'Asia/Dili' + ,'Asia/Dubai' + ,'Asia/Dushanbe' + ,'Asia/Famagusta' + ,'Asia/Gaza' + ,'Asia/Harbin' + ,'Asia/Hebron' + ,'Asia/Ho_Chi_Minh' + ,'Asia/Hong_Kong' + ,'Asia/Hovd' + ,'Asia/Irkutsk' + ,'Asia/Istanbul' + ,'Asia/Jakarta' + ,'Asia/Jayapura' + ,'Asia/Jerusalem' + ,'Asia/Kabul' + ,'Asia/Kamchatka' + ,'Asia/Karachi' + ,'Asia/Kashgar' + ,'Asia/Kathmandu' + ,'Asia/Katmandu' + ,'Asia/Khandyga' + ,'Asia/Kolkata' + ,'Asia/Krasnoyarsk' + ,'Asia/Kuala_Lumpur' + ,'Asia/Kuching' + ,'Asia/Kuwait' + ,'Asia/Macao' + ,'Asia/Macau' + ,'Asia/Magadan' + ,'Asia/Makassar' + ,'Asia/Manila' + ,'Asia/Muscat' + ,'Asia/Nicosia' + ,'Asia/Novokuznetsk' + ,'Asia/Novosibirsk' + ,'Asia/Omsk' + ,'Asia/Oral' + ,'Asia/Phnom_Penh' + ,'Asia/Pontianak' + ,'Asia/Pyongyang' + ,'Asia/Qatar' + ,'Asia/Qostanay' + ,'Asia/Qyzylorda' + ,'Asia/Rangoon' + ,'Asia/Riyadh' + ,'Asia/Saigon' + ,'Asia/Sakhalin' + ,'Asia/Samarkand' + ,'Asia/Seoul' + ,'Asia/Shanghai' + ,'Asia/Singapore' + ,'Asia/Srednekolymsk' + ,'Asia/Taipei' + ,'Asia/Tashkent' + ,'Asia/Tbilisi' + ,'Asia/Tehran' + ,'Asia/Tel_Aviv' + ,'Asia/Thimbu' + ,'Asia/Thimphu' + ,'Asia/Tokyo' + ,'Asia/Tomsk' + ,'Asia/Ujung_Pandang' + ,'Asia/Ulaanbaatar' + ,'Asia/Ulan_Bator' + ,'Asia/Urumqi' + ,'Asia/Ust-Nera' + ,'Asia/Vientiane' + ,'Asia/Vladivostok' + ,'Asia/Yakutsk' + ,'Asia/Yangon' + ,'Asia/Yekaterinburg' + ,'Asia/Yerevan' + ,'Atlantic/Azores' + ,'Atlantic/Bermuda' + ,'Atlantic/Canary' + ,'Atlantic/Cape_Verde' + ,'Atlantic/Faeroe' + ,'Atlantic/Faroe' + ,'Atlantic/Jan_Mayen' + ,'Atlantic/Madeira' + ,'Atlantic/Reykjavik' + ,'Atlantic/South_Georgia' + ,'Atlantic/St_Helena' + ,'Atlantic/Stanley' + ,'Australia/ACT' + ,'Australia/Adelaide' + ,'Australia/Brisbane' + ,'Australia/Broken_Hill' + ,'Australia/Canberra' + ,'Australia/Currie' + ,'Australia/Darwin' + ,'Australia/Eucla' + ,'Australia/Hobart' + ,'Australia/LHI' + ,'Australia/Lindeman' + ,'Australia/Lord_Howe' + ,'Australia/Melbourne' + ,'Australia/NSW' + ,'Australia/North' + ,'Australia/Perth' + ,'Australia/Queensland' + ,'Australia/South' + ,'Australia/Sydney' + ,'Australia/Tasmania' + ,'Australia/Victoria' + ,'Australia/West' + ,'Australia/Yancowinna' + ,'Brazil/Acre' + ,'Brazil/DeNoronha' + ,'Brazil/East' + ,'Brazil/West' + ,'CET' + ,'CST6CDT' + ,'Canada/Atlantic' + ,'Canada/Central' + ,'Canada/Eastern' + ,'Canada/Mountain' + ,'Canada/Newfoundland' + ,'Canada/Pacific' + ,'Canada/Saskatchewan' + ,'Canada/Yukon' + ,'Chile/Continental' + ,'Chile/EasterIsland' + ,'Cuba' + ,'EET' + ,'EST' + ,'EST5EDT' + ,'Egypt' + ,'Eire' + ,'Etc/GMT' + ,'Etc/GMT+0' + ,'Etc/GMT+1' + ,'Etc/GMT+10' + ,'Etc/GMT+11' + ,'Etc/GMT+12' + ,'Etc/GMT+2' + ,'Etc/GMT+3' + ,'Etc/GMT+4' + ,'Etc/GMT+5' + ,'Etc/GMT+6' + ,'Etc/GMT+7' + ,'Etc/GMT+8' + ,'Etc/GMT+9' + ,'Etc/GMT-0' + ,'Etc/GMT-1' + ,'Etc/GMT-10' + ,'Etc/GMT-11' + ,'Etc/GMT-12' + ,'Etc/GMT-13' + ,'Etc/GMT-14' + ,'Etc/GMT-2' + ,'Etc/GMT-3' + ,'Etc/GMT-4' + ,'Etc/GMT-5' + ,'Etc/GMT-6' + ,'Etc/GMT-7' + ,'Etc/GMT-8' + ,'Etc/GMT-9' + ,'Etc/GMT0' + ,'Etc/Greenwich' + ,'Etc/UCT' + ,'Etc/UTC' + ,'Etc/Universal' + ,'Etc/Zulu' + ,'Europe/Amsterdam' + ,'Europe/Andorra' + ,'Europe/Astrakhan' + ,'Europe/Athens' + ,'Europe/Belfast' + ,'Europe/Belgrade' + ,'Europe/Berlin' + ,'Europe/Bratislava' + ,'Europe/Brussels' + ,'Europe/Bucharest' + ,'Europe/Budapest' + ,'Europe/Busingen' + ,'Europe/Chisinau' + ,'Europe/Copenhagen' + ,'Europe/Dublin' + ,'Europe/Gibraltar' + ,'Europe/Guernsey' + ,'Europe/Helsinki' + ,'Europe/Isle_of_Man' + ,'Europe/Istanbul' + ,'Europe/Jersey' + ,'Europe/Kaliningrad' + ,'Europe/Kiev' + ,'Europe/Kirov' + # -- !! -- ,'Europe/Kyiv' + ,'Europe/Lisbon' + ,'Europe/Ljubljana' + ,'Europe/London' + ,'Europe/Luxembourg' + ,'Europe/Madrid' + ,'Europe/Malta' + ,'Europe/Mariehamn' + ,'Europe/Minsk' + ,'Europe/Monaco' + ,'Europe/Moscow' + ,'Europe/Nicosia' + ,'Europe/Oslo' + ,'Europe/Paris' + ,'Europe/Podgorica' + ,'Europe/Prague' + ,'Europe/Riga' + ,'Europe/Rome' + ,'Europe/Samara' + ,'Europe/San_Marino' + ,'Europe/Sarajevo' + ,'Europe/Saratov' + ,'Europe/Simferopol' + ,'Europe/Skopje' + ,'Europe/Sofia' + ,'Europe/Stockholm' + ,'Europe/Tallinn' + ,'Europe/Tirane' + ,'Europe/Tiraspol' + ,'Europe/Ulyanovsk' + ,'Europe/Uzhgorod' + ,'Europe/Vaduz' + ,'Europe/Vatican' + ,'Europe/Vienna' + ,'Europe/Vilnius' + ,'Europe/Volgograd' + ,'Europe/Warsaw' + ,'Europe/Zagreb' + ,'Europe/Zaporozhye' + ,'Europe/Zurich' + ,'Factory' + ,'GB' + ,'GB-Eire' + ,'GMT+0' + ,'GMT-0' + ,'GMT0' + ,'Greenwich' + ,'HST' + ,'Hongkong' + ,'Iceland' + ,'Indian/Antananarivo' + ,'Indian/Chagos' + ,'Indian/Christmas' + ,'Indian/Cocos' + ,'Indian/Comoro' + ,'Indian/Kerguelen' + ,'Indian/Mahe' + ,'Indian/Maldives' + ,'Indian/Mauritius' + ,'Indian/Mayotte' + ,'Indian/Reunion' + ,'Iran' + ,'Israel' + ,'Jamaica' + ,'Japan' + ,'Kwajalein' + ,'Libya' + ,'MET' + ,'MST' + ,'MST7MDT' + ,'Mexico/BajaNorte' + ,'Mexico/BajaSur' + ,'Mexico/General' + ,'NZ' + ,'NZ-CHAT' + ,'Navajo' + ,'PRC' + ,'PST8PDT' + ,'Pacific/Apia' + ,'Pacific/Auckland' + ,'Pacific/Bougainville' + ,'Pacific/Chatham' + ,'Pacific/Chuuk' + ,'Pacific/Easter' + ,'Pacific/Efate' + ,'Pacific/Enderbury' + ,'Pacific/Fakaofo' + ,'Pacific/Fiji' + ,'Pacific/Funafuti' + ,'Pacific/Galapagos' + ,'Pacific/Gambier' + ,'Pacific/Guadalcanal' + ,'Pacific/Guam' + ,'Pacific/Honolulu' + ,'Pacific/Johnston' + # -- !! -- ,'Pacific/Kanton' + ,'Pacific/Kiritimati' + ,'Pacific/Kosrae' + ,'Pacific/Kwajalein' + ,'Pacific/Majuro' + ,'Pacific/Marquesas' + ,'Pacific/Midway' + ,'Pacific/Nauru' + ,'Pacific/Niue' + ,'Pacific/Norfolk' + ,'Pacific/Noumea' + ,'Pacific/Pago_Pago' + ,'Pacific/Palau' + ,'Pacific/Pitcairn' + ,'Pacific/Pohnpei' + ,'Pacific/Ponape' + ,'Pacific/Port_Moresby' + ,'Pacific/Rarotonga' + ,'Pacific/Saipan' + ,'Pacific/Samoa' + ,'Pacific/Tahiti' + ,'Pacific/Tarawa' + ,'Pacific/Tongatapu' + ,'Pacific/Truk' + ,'Pacific/Wake' + ,'Pacific/Wallis' + ,'Pacific/Yap' + ,'Poland' + ,'Portugal' + ,'ROC' + ,'ROK' + ,'Singapore' + ,'Turkey' + ,'UCT' + ,'US/Alaska' + ,'US/Aleutian' + ,'US/Arizona' + ,'US/Central' + ,'US/East-Indiana' + ,'US/Eastern' + ,'US/Hawaii' + ,'US/Indiana-Starke' + ,'US/Michigan' + ,'US/Mountain' + ,'US/Pacific' + ,'US/Samoa' + ,'UTC' + ,'Universal' + ,'W-SU' + ,'WET' + ,'Zulu' + ] + + problematic_timezones_map = {} + with act.db.connect() as con: + cur = con.cursor() + # random.choice(fb_time_zones) + for tz_name in fb_time_zones: + try: + tz_info = get_timezone(tz_name) + # print(tz_name) + tm_region = ( + datetime.time(11, 22, 33, 561400, get_timezone(tz_name)) + ,datetime.time(12, 23, 34, 672400, get_timezone(tz_name)) + ,datetime.time(13, 24, 35, 783400, get_timezone(tz_name)) + ) + ts_region = ( + datetime.datetime(2020, 10, 20, 11, 22, 33, 561400, get_timezone(tz_name)) + ,datetime.datetime(2021, 11, 21, 12, 23, 34, 672400, get_timezone(tz_name)) + ,datetime.datetime(2022, 12, 22, 13, 24, 35, 783400, get_timezone(tz_name)) + ) + + #------------------------------------------------ + cur.execute("insert into test(arr_tmtz, arr_tstz) values (?, ?) returning arr_tmtz,arr_tstz", ( tm_region, ts_region ) ) + inserted_tmtz_array, inserted_tstz_array = cur.fetchone()[:2] + if set(inserted_tmtz_array) == set(tm_region) and set(inserted_tstz_array) == set(ts_region): + pass + else: + print('MISMATCH detected between input data and stored result:') + for i,x in enumerate(inserted_tmtz_array): + print(i, f'Input element (TIME WITH TIME ZONE): {tm_region[i]}', f'; stored data: {x}') + for i,x in enumerate(inserted_tstz_array): + print(i, f'Input element (TIMESTAMP WITH TIME ZONE): {ts_region[i]}', f'; stored data: {x}') + + cur.execute("delete from test") + except Exception as e: + problematic_timezones_map[tz_name] = e.__str__() + + if problematic_timezones_map: + print('Problems detected with time zone(s):') + for k,v in problematic_timezones_map.items(): + print(k,v) + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == '' + act.reset() From ca59cc988bf847cefbaf1a0b0f986da5e1388a91 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 17 Aug 2024 23:17:45 +0300 Subject: [PATCH 0132/1064] Added/Updated tests\bugs\gh_6706_test.py: Confirmed bug on 4.0.0.2336. Solved since 4.0.0.2341. Checked on 6.0.0.438, 5.0.2.1478, 4.0.6.3142. --- tests/bugs/gh_6706_test.py | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 tests/bugs/gh_6706_test.py diff --git a/tests/bugs/gh_6706_test.py b/tests/bugs/gh_6706_test.py new file mode 100644 index 00000000..103fc041 --- /dev/null +++ b/tests/bugs/gh_6706_test.py @@ -0,0 +1,108 @@ +#coding:utf-8 + +""" +ID: issue-6706 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6706 +TITLE: Memory leak when running EXECUTE STATEMENT with named parameters [CORE6475] +DESCRIPTION: + We create stored procedure with PARAMS_COUNT input parameters. + Then EXECUTE BLOCK is generated with call of this SP via EXECUTE STATEMENT which applies EXCESS modifier to all arguments. + Value of memory_info().rss is obtained (for appropriate server process), then run execute block MEASURES_COUNT times + and after this - again get memory_info().rss value. + Ratio between current and initial values of memory_info().rss must be less than MAX_RATIO. +NOTES: + [17.08.2024] pzotov + 1. Problem did exist in FB 4.x up to snapshot 4.0.0.2336. + Commit: https://github.com/FirebirdSQL/firebird/commit/4dfb30a45b767994c074bbfcbb8494b8ada19b33 (23-jan-2021, 15:26) + Before this commit ratio for SS was about 5..6 for SS and about 8..9 for CS. + Since 4.0.0.2341 memory consumption was reduced to ~1.6 ... 1.9 + 2. Database must be created with FW = ON otherwise ratio for all snapshots is about 1.5 (and this seems weird). + 3. Test duration is about 35s. + + Checked on 6.0.0.438, 5.0.2.1478, 4.0.6.3142; 4.0.0.2336, 4.0.0.2341. +""" + +import psutil +import pytest +from firebird.qa import * +import time + +########################### +### S E T T I N G S ### +########################### + +# How many input parameters must have procedure: +PARAMS_COUNT = 1000 + +# How many times we call procedures: +MEASURES_COUNT = 1000 + +# Maximal value for ratio between +# new and initial memory_info().rss values: +# +MAX_RATIO = 3 +############# + +db = db_factory(async_write = False) +act = python_act('db') + +#-------------------------------------------------------------------- + +def get_server_pid(con): + with con.cursor() as cur: + cur.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur.fetchone()[0]) + return fb_pid + +#-------------------------------------------------------------------- + +@pytest.mark.version('>=4.0.0') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + + sp_ddl = """ + create or alter procedure sp_test( + """ + params_lst = '\n'.join( [ (',' if i else '') +f'p_{i} int' for i in range(PARAMS_COUNT) ] ) + sp_ddl = '\n'.join( ("create or alter procedure sp_test(", params_lst, ") returns(x int) as begin x = 1; suspend; end") ) + con.execute_immediate(sp_ddl) + con.commit() + + server_process = psutil.Process(get_server_pid(con)) + + params_lst = ','.join( [ f':p_{i}' for i in range(PARAMS_COUNT) ] ) + passed_args = ','.join( [ f'excess p_{i} := 1' for i in range(PARAMS_COUNT) ] ) + + srv_memo_rss_init = int(server_process.memory_info().rss / 1024) + srv_memo_vms_init = int(server_process.memory_info().vms / 1024) + + cur = con.cursor() + for k in range(MEASURES_COUNT): + + es_sql = f""" + execute block returns(x int) as + begin + execute statement ('select p.x * {k} from sp_test({params_lst}) p') ({passed_args}) + into x; + suspend; + end + """ + cur.execute(es_sql) + for r in cur: + pass + + srv_memo_rss_curr = int(server_process.memory_info().rss / 1024) + srv_memo_vms_curr = int(server_process.memory_info().vms / 1024) + + memo_ratio = srv_memo_rss_curr / srv_memo_rss_init + + SUCCESS_MSG = 'Ratio between memory values measured before and after loop: acceptable' + if memo_ratio < MAX_RATIO: + print(SUCCESS_MSG) + else: + print( 'Ratio: /* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:.2f}'.format(memo_ratio), '{:.2f}'.format(MAX_RATIO) ) ) + + act.expected_stdout = SUCCESS_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 0a909b2c0e9d9f13a621710171db3a38da7cd924 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 18 Aug 2024 20:12:50 +0300 Subject: [PATCH 0133/1064] Added/Updated tests\bugs\gh_2292_test.py: see notes --- tests/bugs/gh_2292_test.py | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/bugs/gh_2292_test.py diff --git a/tests/bugs/gh_2292_test.py b/tests/bugs/gh_2292_test.py new file mode 100644 index 00000000..5a132555 --- /dev/null +++ b/tests/bugs/gh_2292_test.py @@ -0,0 +1,57 @@ +#coding:utf-8 + +""" +ID: issue-2292 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/2292 +TITLE: Isql's extracted script is unusable with interdependent selectable procedures in FB 2.1 [CORE1862] +DESCRIPTION: + Test creates SP which has output parameter *and* SUSPEND clause. + Then we extract metadata and check whether this procedure header contains 'SUSPEND'. + On FB 2.0.7.13318 extracted metadata contains 'EXIT': + CREATE PROCEDURE SP_TEST RETURNS (O INTEGER) + AS + BEGIN EXIT; END ^ + + Although such code can be compiled, this SP could be called (and returned empty resultset) only in 2.0.7 and before. + Since 2.1 attempt to call such SP will raise: + Statement failed, SQLSTATE = 42000 + ... + -invalid request BLR at offset ... + -Procedure SP_TEST is not selectable (it does not contain a SUSPEND statement) +""" + +import re +import pytest +from firebird.qa import * + +init_sql = """ + set term ^ ; + create or alter procedure sp_test returns(out_value int) as + begin + out_value = 1; + suspend; + end + ^ + set term ;^ + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, capsys): + + meta_sql = act.extract_meta() + EXPECTED_MSG = 'OK' + + p = re.compile(r'SP_TEST\s+RETURNS \(OUT_VALUE INTEGER\)\s+AS\s+BEGIN\s+SUSPEND;\s+END\s?\^', re.IGNORECASE) + + if p.search(meta_sql): + print(EXPECTED_MSG) + else: + print(f'Could not find pattern "{p.pattern}" in extracted metadata.') + print(meta_sql) + + act.expected_stdout = EXPECTED_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 4ee56973b45e691a625d0c25ce5a50738e3e8ab5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 18 Aug 2024 22:06:35 +0300 Subject: [PATCH 0134/1064] Added/Updated tests\bugs\gh_8213_test.py: Checked on 5.0.2.1479. NB: 6.x not yet has fix, waiting for front-porting. --- tests/bugs/gh_8213_test.py | 281 +++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 tests/bugs/gh_8213_test.py diff --git a/tests/bugs/gh_8213_test.py b/tests/bugs/gh_8213_test.py new file mode 100644 index 00000000..a0e4f190 --- /dev/null +++ b/tests/bugs/gh_8213_test.py @@ -0,0 +1,281 @@ +#coding:utf-8 + +""" +ID: issue-8213 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8213 +TITLE: WHEN NOT MATCHED BY SOURCE - does not work with a direct table as source +DESCRIPTION: +NOTES: + [18.08.2024] pzotov + Checked on 5.0.2.1479. + NB: 6.x not yet has fix, waiting for front-porting. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate procedure sp_main as begin end; + recreate table test (id smallint); + recreate generator g; + recreate table test ( + id smallint primary key, + typ smallint, + cat smallint + ); + commit; + + set term ^ ; + create or alter trigger test_bi0 for test active before insert position 0 as + begin + new.id = coalesce(new.id, gen_id(g, 1)); + end + ^ + set term ; ^ + commit; + + insert into test(typ, cat) values(1, 10); + insert into test(typ, cat) values(1, 20); + insert into test(typ, cat) values(2, 10); + insert into test(typ, cat) values(2, 30); + commit; + + set term ^; + recreate procedure sp_main ( + a_insert_using_sp boolean, + a_delete_using_sp boolean, + a_source_typ smallint, + a_target_typ smallint + ) as + + declare procedure inner_sp_data_for_source_typ + returns ( + id smallint, + typ smallint, + cat smallint + ) as + begin + for select t.id, + t.typ, + t.cat + from test t + where t.typ = :a_source_typ + into :id, + :typ, + :cat + do + begin + suspend; + end + end + + begin + + if ( a_insert_using_sp or :a_delete_using_sp ) then + begin + if (a_insert_using_sp) then + merge into test t + using inner_sp_data_for_source_typ s + on t.typ = :a_target_typ and + t.cat = s.cat + when not matched by target then + insert (typ, cat) values (:a_target_typ, s.cat); + else + merge into test t + using test s + on t.typ = :a_target_typ and + t.cat = s.cat + when not matched by target then + insert (typ, cat) values (:a_target_typ, s.cat); + + if (a_delete_using_sp) then + merge into test t + using inner_sp_data_for_source_typ s on t.cat = s.cat + when not matched by source and t.typ = :a_target_typ then + delete; + else + merge into test t + using test s on t.cat = s.cat + when not matched by source and t.typ = :a_target_typ then + delete; + + end + else + begin + -- works as expected + merge into test t + using ( select t.id, + t.typ, + t.cat + from test t + where t.typ = :a_source_typ + ) s + on t.typ = :a_target_typ and + t.cat = s.cat + when not matched by target then + insert (typ, cat) values (:a_target_typ, s.cat); + + merge into test t + using ( select t.id, + t.typ, + t.cat + from test t + where t.typ = :a_source_typ + ) s + on t.cat = s.cat + when not matched by source and t.typ = :a_target_typ then + delete; + end + end + ^ + set term ;^ + commit; + + -- select * from test; + set count on; + + alter sequence g restart with 1000; + execute procedure sp_main(true, true, 1, 10); + select 'INS:SP, DEL:SP' msg, t.id, t.typ, t.cat from test t order by id; + rollback; + + alter sequence g restart with 1000; + execute procedure sp_main(true, false, 1, 10); + select 'INS:SP, DEL:TAB' msg, t.id, t.typ, t.cat from test t order by id; + rollback; + + alter sequence g restart with 1000; + execute procedure sp_main(false, true, 1, 10); + select 'INS:TAB, DEL:SP' msg, t.id, t.typ, t.cat from test t order by id; + rollback; + + alter sequence g restart with 1000; + execute procedure sp_main(false, false, 1, 10); + select 'INS:TAB, DEL:TAB' msg, t.id, t.typ, t.cat from test t order by id; + rollback; +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + MSG INS:SP, DEL:SP + ID 1 + TYP 1 + CAT 10 + MSG INS:SP, DEL:SP + ID 2 + TYP 1 + CAT 20 + MSG INS:SP, DEL:SP + ID 3 + TYP 2 + CAT 10 + MSG INS:SP, DEL:SP + ID 4 + TYP 2 + CAT 30 + MSG INS:SP, DEL:SP + ID 1000 + TYP 10 + CAT 10 + MSG INS:SP, DEL:SP + ID 1001 + TYP 10 + CAT 20 + Records affected: 6 + + MSG INS:SP, DEL:TAB + ID 1 + TYP 1 + CAT 10 + MSG INS:SP, DEL:TAB + ID 2 + TYP 1 + CAT 20 + MSG INS:SP, DEL:TAB + ID 3 + TYP 2 + CAT 10 + MSG INS:SP, DEL:TAB + ID 4 + TYP 2 + CAT 30 + MSG INS:SP, DEL:TAB + ID 1000 + TYP 10 + CAT 10 + MSG INS:SP, DEL:TAB + ID 1001 + TYP 10 + CAT 20 + Records affected: 6 + + MSG INS:TAB, DEL:SP + ID 1 + TYP 1 + CAT 10 + MSG INS:TAB, DEL:SP + ID 2 + TYP 1 + CAT 20 + MSG INS:TAB, DEL:SP + ID 3 + TYP 2 + CAT 10 + MSG INS:TAB, DEL:SP + ID 4 + TYP 2 + CAT 30 + MSG INS:TAB, DEL:SP + ID 1000 + TYP 10 + CAT 10 + MSG INS:TAB, DEL:SP + ID 1001 + TYP 10 + CAT 20 + MSG INS:TAB, DEL:SP + ID 1002 + TYP 10 + CAT 10 + Records affected: 7 + + MSG INS:TAB, DEL:TAB + ID 1 + TYP 1 + CAT 10 + MSG INS:TAB, DEL:TAB + ID 2 + TYP 1 + CAT 20 + MSG INS:TAB, DEL:TAB + ID 3 + TYP 2 + CAT 10 + MSG INS:TAB, DEL:TAB + ID 4 + TYP 2 + CAT 30 + MSG INS:TAB, DEL:TAB + ID 1000 + TYP 10 + CAT 10 + MSG INS:TAB, DEL:TAB + ID 1001 + TYP 10 + CAT 20 + Records affected: 6 +""" + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action): + + if act.is_version('>=6'): + pytest.skip('NOTE: 6.x not yet fixed, waiting for front-porting.') + + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From ee82da2fc76e02057ef291107c405c4d97e2787d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 18 Aug 2024 22:18:06 +0300 Subject: [PATCH 0135/1064] Added/Updated tests\bugs\core_6239_test.py: minor change: added comments --- tests/bugs/core_6239_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_6239_test.py b/tests/bugs/core_6239_test.py index 1b42fe80..39e436ef 100644 --- a/tests/bugs/core_6239_test.py +++ b/tests/bugs/core_6239_test.py @@ -2,11 +2,14 @@ """ ID: issue-6483 -ISSUE: 6483 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6483 TITLE: Procedures and EXECUTE BLOCK without RETURNS should not be allowed to use SUSPEND DESCRIPTION: JIRA: CORE-6239 FBTEST: bugs.core_6239 +NOTES: + Fix was done by commit https://github.com/FirebirdSQL/firebird/commit/b2b5f9a87cea26a9f12fa231804dba9d0426d3fa + (can be checked by 4.0.0.1763+, date of build since 05-feb-2020). """ import pytest From 37b2159e667ca1220fc37066d19bda0e52fd9d75 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 20 Aug 2024 06:12:38 +0300 Subject: [PATCH 0136/1064] Added/Updated tests\bugs\gh_8213_test.py: Removed pytest.skip for FB 6.x. Checked on 6.0.0.438-d40d01b, 5.0.2.1479-47aa3b1 -- all fine --- tests/bugs/gh_8213_test.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_8213_test.py b/tests/bugs/gh_8213_test.py index a0e4f190..9dea50ed 100644 --- a/tests/bugs/gh_8213_test.py +++ b/tests/bugs/gh_8213_test.py @@ -6,9 +6,8 @@ TITLE: WHEN NOT MATCHED BY SOURCE - does not work with a direct table as source DESCRIPTION: NOTES: - [18.08.2024] pzotov - Checked on 5.0.2.1479. - NB: 6.x not yet has fix, waiting for front-porting. + [20.08.2024] pzotov + Checked on 6.0.0.438-d40d01b, 5.0.2.1479-47aa3b1 """ import pytest @@ -272,10 +271,6 @@ @pytest.mark.version('>=5.0.2') def test_1(act: Action): - - if act.is_version('>=6'): - pytest.skip('NOTE: 6.x not yet fixed, waiting for front-porting.') - act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ee0cb57280614a20648d208d1b175fa266adca7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 20 Aug 2024 16:57:44 +0300 Subject: [PATCH 0137/1064] Added/Updated tests\bugs\gh_8221_test.py: Checked on 6.0.0.438-d9f9b28, 5.0.2.1479-adfe97a, 4.0.6.3142-984ccb9 --- tests/bugs/gh_8221_test.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/bugs/gh_8221_test.py diff --git a/tests/bugs/gh_8221_test.py b/tests/bugs/gh_8221_test.py new file mode 100644 index 00000000..b97e724d --- /dev/null +++ b/tests/bugs/gh_8221_test.py @@ -0,0 +1,38 @@ +#coding:utf-8 + +""" +ID: issue-8221 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8221 +TITLE: Crash when MAKE_DBKEY() is called with 0 or 1 arguments +DESCRIPTION: +NOTES: + [20.08.2024] pzotov + Confirmed crash on 6.0.0.438-d40d01b (dob: 20.08.2024 04:44). + Checked on 6.0.0.438-d9f9b28, 5.0.2.1479-adfe97a, 4.0.6.3142-984ccb9 +""" +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail OFF; + select 1 from rdb$database where rdb$db_key = make_dbkey(); + select 1 from rdb$database where rdb$db_key = make_dbkey('RDB$DATABASE'); +""" + +act = isql_act('db', test_script, substitutions=[ ('[ \\t]+', ' ') ]) + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + + expected_stdout = f""" + Statement failed, SQLSTATE = 39000 + function MAKE_DBKEY could not be matched + + Statement failed, SQLSTATE = 39000 + function MAKE_DBKEY could not be matched + """ + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From ad1485746ab78f44dca3e19bb0bdd004408b7a1d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 21 Aug 2024 11:29:33 +0300 Subject: [PATCH 0138/1064] Added/Updated tests\bugs\gh_4954_test.py: Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. --- tests/bugs/gh_4954_test.py | 150 +++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 tests/bugs/gh_4954_test.py diff --git a/tests/bugs/gh_4954_test.py b/tests/bugs/gh_4954_test.py new file mode 100644 index 00000000..502ffdf5 --- /dev/null +++ b/tests/bugs/gh_4954_test.py @@ -0,0 +1,150 @@ +#coding:utf-8 + +""" +ID: issue-4954 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/4954 +TITLE: subselect losing the index when where clause includes coalesce() [CORE4640] +DESCRIPTION: +NOTES: + [21.08.2024] pzotov + Confirmed bug on 2.1.7.18553. No such problem on 2.5.927156. + Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. +""" +import pytest +from firebird.qa import * + +init_sql = """ + recreate table t1 ( + id int not null, + vc1 varchar(1) not null, + i1 int not null, + i2 int not null, + constraint t1_pk primary key (id) using descending index t1_pk, + constraint t1_uk1 unique (i1, i2, vc1) + ); + + recreate table t2 ( + id int not null, + vc1 varchar(1) not null, + i1 int not null, + i2 int not null, + constraint t2_pk primary key (id) using descending index t2_pk, + constraint t2_uk1 unique (i1, i2, vc1) + ); + + recreate table t3 ( + id int not null, + i1_1 int, + i1_2 int + ); + + create view v1 (ID, VC1, I1, I2) as + select t1.id, t1.vc1, t1.i1, t1.i2 + from t1 + union all + select t2.id, t2.vc1, t2.i1, t2.i2 + from t2; + commit; + + insert into t1 (id, vc1, i1, i2) values (9, 'a', 1009, 1000); + insert into t1 (id, vc1, i1, i2) values (8, 'a', 1008, 1000); + insert into t1 (id, vc1, i1, i2) values (7, 'a', 1007, 1000); + insert into t1 (id, vc1, i1, i2) values (6, 'a', 1006, 1000); + insert into t1 (id, vc1, i1, i2) values (5, 'a', 1005, 1000); + insert into t1 (id, vc1, i1, i2) values (4, 'a', 1004, 1000); + insert into t1 (id, vc1, i1, i2) values (3, 'a', 1003, 1000); + insert into t1 (id, vc1, i1, i2) values (2, 'a', 1002, 1000); + insert into t1 (id, vc1, i1, i2) values (1, 'a', 1001, 1000); + + + insert into t2 (id, vc1, i1, i2) values (19, 'a', 1019, 1000); + insert into t2 (id, vc1, i1, i2) values (18, 'a', 1018, 1000); + insert into t2 (id, vc1, i1, i2) values (17, 'a', 1017, 1000); + insert into t2 (id, vc1, i1, i2) values (16, 'a', 1016, 1000); + insert into t2 (id, vc1, i1, i2) values (15, 'a', 1015, 1000); + insert into t2 (id, vc1, i1, i2) values (14, 'a', 1014, 1000); + insert into t2 (id, vc1, i1, i2) values (13, 'a', 1013, 1000); + insert into t2 (id, vc1, i1, i2) values (12, 'a', 1012, 1000); + insert into t2 (id, vc1, i1, i2) values (11, 'a', 1011, 1000); + insert into t2 (id, vc1, i1, i2) values (10, 'a', 1010, 1000); + + + insert into t3 (id, i1_1, i1_2) values (100000, null, 1010); + insert into t3 (id, i1_1, i1_2) values (100001, 1012, null); + commit; + set statistics index t1_pk; + set statistics index t2_pk; + set statistics index t1_uk1; + set statistics index t2_uk1; + 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('>=3.0') +def test_1(act: Action, capsys): + + test_sql = """ + select t3.id, + (select first 1 v1.id + from v1 + where + v1.vc1 = 'A' + and v1.i2 = 1000 + and v1.i1 = coalesce(t3.i1_1, t3.i1_2) + ) + from t3 + """ + + 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')]) ) + + expected_plan_4x = """ + Select Expression + ....-> Singularity Check + ........-> First N Records + ............-> Filter + ................-> Union + ....................-> Filter + ........................-> Table "T1" as "V1 T1" Access By ID + ............................-> Bitmap + ................................-> Index "T1_UK1" Unique Scan + ....................-> Filter + ........................-> Table "T2" as "V1 T2" Access By ID + ............................-> Bitmap + ................................-> Index "T2_UK1" Unique Scan + Select Expression + ....-> Table "T3" Full Scan + """ + expected_plan_5x = """ + Sub-query + ....-> Singularity Check + ........-> First N Records + ............-> Filter + ................-> Filter + ....................-> Union + ........................-> Filter + ............................-> Table "T1" as "V1 T1" Access By ID + ................................-> Bitmap + ....................................-> Index "T1_UK1" Unique Scan + ........................-> Filter + ............................-> Table "T2" as "V1 T2" Access By ID + ................................-> Bitmap + ....................................-> Index "T2_UK1" Unique Scan + Select Expression + ....-> Table "T3" Full Scan + """ + act.expected_stdout = expected_plan_4x if act.is_version('<5') else expected_plan_5x + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From de5f3959e042c3b9391ac0956a888d2ea4435d9c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 21 Aug 2024 13:58:34 +0300 Subject: [PATCH 0139/1064] Added alias for upcoming test --- files/qa-databases.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index 5681f655..ab590f5a 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -269,6 +269,10 @@ tmp_fd0fa8a3_alias = $(dir_sampleDb)/qa/tmp_fd0fa8a3.fdb TempTableDirectory = <> } +tmp_gh_6416_alias = $(dir_sampleDb)/qa/tmp_gh_6416.fdb +{ + DataTypeCompatibility = 3.0 +} # Databases for replication tests: # From c7f75bf41d825f7281311c5ce81b40ea95a80635 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 21 Aug 2024 13:58:58 +0300 Subject: [PATCH 0140/1064] Added/Updated tests\bugs\gh_6416_test.py: Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142. --- tests/bugs/gh_6416_test.py | 143 +++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 tests/bugs/gh_6416_test.py diff --git a/tests/bugs/gh_6416_test.py b/tests/bugs/gh_6416_test.py new file mode 100644 index 00000000..9b2ca65a --- /dev/null +++ b/tests/bugs/gh_6416_test.py @@ -0,0 +1,143 @@ +#coding:utf-8 + +""" +ID: issue-6416 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6416 +TITLE: Engine cant determine datatype in SQL: Unknown SQL Data type (32752) [CORE6168] +DESCRIPTION: + Test creates table with columns belonging to "new datatypes" family: int128, decfloat and time[stamp] with time zone. + Also, one record is added into this table with values which are valid for numeric types in FB 4.x+ (time zone fields + can remain null or arbitrary). + This DB is them copied to another DB (using file-level call of shutil.copy2()). + Another DB filename must match to the specified in the databases.conf (alias defined by 'REQUIRED_ALIAS' variable). + Its alias has special value for DataTypeCompatibility parameter. Connection to this DB and query to a table with 'new datatypes' + must return SQLDA with *old* types which are known for FB versions prior 4.x. + + Then we repeat same query to 'initial' test DB and must get SQLDA with actual values for all new columns (known since FB 4.x). +NOTES: + [18.08.2022] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Database file for REQUIRED_ALIAS must NOT exist in the QA_root/files/qa/ subdirectory: it will be created here. + Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace + it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + 3. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + + Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142. +""" + +import re +from pathlib import Path +import shutil + +import pytest +from firebird.qa import * + +# Pre-defined alias for test DB in the QA_root/files/qa-databases.conf. +# This file (qa-databases.conf) must be copied manually to each testing +# FB home folder, with replacing databases.conf there: +# +REQUIRED_ALIAS = 'tmp_gh_6416_alias' + +init_sql = f''' + set bail on; + recreate table test( + f_sml smallint default -32768 + ,f_int int default -2147483648 + ,f_big bigint default -9223372036854775808 + ,f_128 int128 default -170141183460469231731687303715884105728 + ,f_num numeric(38) default -170141183460469231731687303715884105728 + ,f_dec decfloat default -9.999999999999999999999999999999999E+6144 + ,f_tz time with time zone default '01:02:03 Indian/Cocos' + ,f_tsz timestamp with time zone default '22.09.2023 01:02:03 Indian/Cocos' + ); + insert into test default values; + commit; +''' + +db = db_factory(init = init_sql) + +substitutions = [('^((?!(SQLSTATE|error|Floating-point overflow|sqltype)).)*$', ''), ('[ \t]+', ' ')] +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_db_for_3x_client). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_6416_alias = $(dir_sampleDb)/qa/tmp_gh_6416.fdb + # - then we extract filename: 'tmp_gh_6416.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + # Full path + filename of database to which we will try to connect: + # + tmp_db_for_3x_client = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) + shutil.copy2(act.db.db_path, tmp_db_for_3x_client) + + test_sql = f''' + set bail on; + set list on; + connect '{REQUIRED_ALIAS}' user {act.db.user}; + -- select mon$database_name from mon$database; + set sqlda_display on; + select * + from test; + ''' + + act.expected_stdout = f""" + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 05: sqltype: 580 INT64 Nullable scale: 0 subtype: 1 len: 8 + 06: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + 07: sqltype: 560 TIME Nullable scale: 0 subtype: 0 len: 4 + 08: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 + Statement failed, SQLSTATE = 22003 + -SQL error code = -303 + -Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + """ + + act.isql(switches = ['-q'], input = test_sql, combine_output = True, credentials = False, connect_db = False) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + tmp_db_for_3x_client.unlink() + + #------------------------------------------------------------- + + test_sql = f''' + set bail on; + set list on; + set sqlda_display on; + select * + from test; + ''' + act.expected_stdout = """ + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + 05: sqltype: 32752 INT128 Nullable scale: 0 subtype: 1 len: 16 + 06: sqltype: 32762 DECFLOAT(34) Nullable scale: 0 subtype: 0 len: 16 + 07: sqltype: 32756 TIME WITH TIME ZONE Nullable scale: 0 subtype: 0 len: 8 + 08: sqltype: 32754 TIMESTAMP WITH TIME ZONE Nullable scale: 0 subtype: 0 len: 12 + """ + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From f5fc896942ed2b9b5f537e719634e7ad3409208c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 22 Aug 2024 16:09:49 +0300 Subject: [PATCH 0141/1064] Added/Updated tests\bugs\gh_7092_test.py: changed ratio and limits - see notes. --- tests/bugs/gh_7092_test.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/tests/bugs/gh_7092_test.py b/tests/bugs/gh_7092_test.py index d89ee1ff..6e505e2b 100644 --- a/tests/bugs/gh_7092_test.py +++ b/tests/bugs/gh_7092_test.py @@ -13,15 +13,20 @@ We do these measures times for each SP, and each result is added to the list which, in turn, is the source for median evaluation. Finally, we get ratio between minimal and maximal medians (see 'median_ratio') - On Windows 8.1 usually this ratio is about 7 (before fix it was more than 100). + This ratio is about: + * Windows: 0.6 ... 0.7 + * Linux: 0.5 ... 0.6 + Before fix it was more than 10. Test is considered as passed if median_ratio less than threshold . NOTES: + Number of iterations for loops differ: we have to perform 'sp_empty_loop' at least 1E6 times + in order to get valuable difference between CPU user time counters and use it as denomitator. + Procedure 'sp_ctime_loop' must be called for 10x times LESS than 'sp_empty_loop'. + Confirmed problem on: - 4.0.1.2699 (01-jan-2022): median ratio was 109 ... 110 (3.40 vs 0.03) - 5.0.0.362 (01-jan-2022): median ratio was 111 ... 113 (3.51 vs 0.03) + 5.0.0.362, 4.0.1.2699 (bith snapshots have date 01-jan-2022) Checked on 6.0.0.195, 5.0.0.1305, 4.0.5.3049. - Scope of median ratio values: 4.33 ... 7.00 """ import psutil @@ -43,12 +48,13 @@ def median(lst): N_MEASURES = 15 # How many iterations must be done: -N_COUNT_PER_MEASURE = 100000 +N_COUNT_TIME_LOOP = 100000 +N_COUNT_EMPTY_LOOP = 1000000 # Maximal value for ratio between maximal and minimal medians # -MAX_RATIO = 15 -############## +MAX_RATIO = 1.5 +############### init_script = \ f''' @@ -60,12 +66,12 @@ def median(lst): begin while (n < a_limit) do begin - n = n + 1; d = current_time; + n = n + 1; end end ^ - create procedure sp_dummy_loop(a_limit int) + create procedure sp_empty_loop(a_limit int) as declare n int = 1; begin @@ -79,7 +85,7 @@ def median(lst): ^ ''' -db = db_factory(init = init_script) +db = db_factory(init = init_script, charset = 'win1251') act = python_act('db') expected_stdout = """ @@ -96,24 +102,25 @@ def test_1(act: Action, capsys): sp_time = {} for i in range(0, N_MEASURES): - for sp_name in ('sp_ctime_loop', 'sp_dummy_loop'): + for sp_name in ('sp_ctime_loop', 'sp_empty_loop'): + n_count = N_COUNT_TIME_LOOP if sp_name == 'sp_ctime_loop' else N_COUNT_EMPTY_LOOP fb_info_init = psutil.Process(fb_pid).cpu_times() - cur.callproc( sp_name, (N_COUNT_PER_MEASURE,) ) + cur.callproc( sp_name, (n_count,) ) fb_info_curr = psutil.Process(fb_pid).cpu_times() sp_time[ sp_name, i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) sp_ctime_median = median([v for k,v in sp_time.items() if k[0] == 'sp_ctime_loop']) - sp_dummy_median = median([v for k,v in sp_time.items() if k[0] == 'sp_dummy_loop']) + sp_dummy_median = median([v for k,v in sp_time.items() if k[0] == 'sp_empty_loop']) #---------------------------------- median_ratio = sp_ctime_median / sp_dummy_median print( 'Medians ratio: ' + ('acceptable' if median_ratio <= MAX_RATIO else '/* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:9g}'.format(median_ratio), '{:9g}'.format(MAX_RATIO) ) ) ) if median_ratio > MAX_RATIO: - print('CPU times for each of {N_MEASURES} measures:') + print(f'CPU times for each of {N_MEASURES} measures:') for k,v in sp_time.items(): print(k,':::',v) - print(f'Median cpu time for {N_MEASURES} measures using loops for {N_COUNT_PER_MEASURE} iterations in each SP call:') + print(f'Median cpu time for {N_MEASURES} measures:') print('sp_ctime_median:',sp_ctime_median) print('sp_dummy_median:',sp_dummy_median) print('median_ratio:',median_ratio) From d3e21985ab3b3d79e6b7f15fc012c6c46257524b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 22 Aug 2024 21:50:18 +0300 Subject: [PATCH 0142/1064] Added/Updated tests\bugs\core_4386_test.py: Reimplemented, see notes. --- tests/bugs/core_4386_test.py | 317 ++++++++++++++++++++++++++++------- 1 file changed, 259 insertions(+), 58 deletions(-) diff --git a/tests/bugs/core_4386_test.py b/tests/bugs/core_4386_test.py index ee5438df..943180c6 100644 --- a/tests/bugs/core_4386_test.py +++ b/tests/bugs/core_4386_test.py @@ -9,20 +9,32 @@ FBTEST: bugs.core_4386 NOTES: [22.11.2021] pcisar - This test requires READ_COMMITTED_NO_RECORD_VERSION transaction to work, which - requires ReadConsistency disabled in FB 4. However, it does not work as expected - because all drop commands pass without exception even with ReadConsistency disabled. - The same happens under 3.0.8 (no errors raised). + This test requires READ_COMMITTED_NO_RECORD_VERSION transaction to work, which + requires ReadConsistency disabled in FB 4. However, it does not work as expected + because all drop commands pass without exception even with ReadConsistency disabled. + The same happens under 3.0.8 (no errors raised). [17.09.2022] pzotov - 1. Test actually must work identical for *every* isolation mode of all possible set. - 2. One need to be very careful with object that attempts to make COMMIT after DROP statement: - if we use custom TPB, start transaction explicitly and 'bind' DDL cursor to this transaction - then we have to run commit *exactly* by this TRANSACTION rather then connection whoch owns it! - See 'tx2.commit()' in the code. If we replace it with 'con2.commit()' then Tx2 will be - *silently* rolled back (!!despite that we issued con.commit() !!) and we will not get any - error messages. I'm not sure whether this correct or no. - - Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 + 1. Test actually must work identical for *every* isolation mode of all possible set. + 2. One need to be very careful with object that attempts to make COMMIT after DROP statement: + if we use custom TPB, start transaction explicitly and 'bind' DDL cursor to this transaction + then we have to run commit *exactly* by this TRANSACTION rather then connection whoch owns it! + See 'tx2.commit()' in the code. If we replace it with 'con2.commit()' then Tx2 will be + *silently* rolled back (!!despite that we issued con.commit() !!) and we will not get any + error messages. I'm not sure whether this correct or no. + Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 + + [22.08.2024] pzotov + * Changed DDL because of SubQueryConversion config parameter appearance. + We have to AVOID usage of queries which have plan that can be changed when firebird.conf has + SubQueryConversion = true. In that case some index can be excluded from plan and thus + it can be dropped on first iteration of 'for x_isol in tx_isol_lst' loop. This causes unexpected + error 'index not found' for subsequent checks. + * Added check for error message when we try to drop standalone function. + * Assert moved out to the point after loop in order to show whole result in case of some error + (rather than only one message block for some particular x_isol). + * Excluded check of FB 3.x (this version no more changed). + + Checked on 6.0.0.442, 5.0.2.1479, 4.0.6.3142 """ import pytest @@ -46,17 +58,24 @@ create index test1_id on test1(id); commit; - create descending index test2_id_x_desc on test2(id,x); + create descending index test2_x on test2(x); commit; create or alter view v_test as select id,x from test1 where id between 15 and 30; commit; set term ^; + create or alter function fn_worker(a_x int) returns int as + declare v_id int; + begin + execute statement ('select max(b.id) from test2 b where b.x >= ?') (:a_x) into v_id; + return v_id; + end + ^ create or alter procedure sp_worker(a_id int) returns(x int) as begin for - execute statement ('select v.x from v_test v where v.id = ? and exists(select * from test2 b where b.id = v.id)') (:a_id) + execute statement ('select v.x from v_test v where v.id = ? and v.id >= fn_worker(v.x)') (:a_id) into x do suspend; @@ -84,48 +103,18 @@ commit; """ -expected_stdout = """ - lock conflict on no wait transaction - -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use - (335544345, 335544351, 335544453) - - lock conflict on no wait transaction - -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use - (335544345, 335544351, 335544453) - - lock conflict on no wait transaction - -unsuccessful metadata update - -object VIEW "V_TEST" is in use - (335544345, 335544351, 335544453) - - lock conflict on no wait transaction - -unsuccessful metadata update - -object TABLE "TEST2" is in use - (335544345, 335544351, 335544453) - - lock conflict on no wait transaction - -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use - (335544345, 335544351, 335544453) - - lock conflict on no wait transaction - -unsuccessful metadata update - -object INDEX "TEST2_ID_X_DESC" is in use - (335544345, 335544351, 335544453) -""" - -@pytest.mark.version('>=3.0.6') +@pytest.mark.version('>=4.0') def test_1(act: Action, capsys): act.isql(switches=[], input=ddl_script) - drop_commands = ['drop procedure sp_test', - 'drop procedure sp_worker', - 'drop view v_test', - 'drop table test2', - 'drop index test1_id', - 'drop index test2_id_x_desc'] + drop_commands = [ 'drop procedure sp_test', + 'drop procedure sp_worker', + 'drop function fn_worker', + 'drop view v_test', + 'drop table test2', + 'drop index test1_id', + 'drop index test2_x' + ] tx_isol_lst = [ Isolation.READ_COMMITTED_NO_RECORD_VERSION, Isolation.READ_COMMITTED_RECORD_VERSION, @@ -147,6 +136,7 @@ def test_1(act: Action, capsys): for cmd in drop_commands: with act.db.connect() as con2: custom_tpb = tpb(isolation = x_isol, lock_timeout=0) + print(x_isol.name, cmd) tx2 = con2.transaction_manager(custom_tpb) tx2.begin() cur2 = tx2.cursor() @@ -164,7 +154,218 @@ def test_1(act: Action, capsys): print(e.__str__()) print(e.gds_codes) - act.expected_stdout = expected_stdout - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - act.reset() + act.expected_stdout = f""" + READ_COMMITTED_NO_RECORD_VERSION drop procedure sp_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop procedure sp_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop function fn_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object FUNCTION "FN_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop view v_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object VIEW "V_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop table test2 + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST2" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop index test1_id + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST1_ID" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_NO_RECORD_VERSION drop index test2_x + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST2_X" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop procedure sp_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop procedure sp_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop function fn_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object FUNCTION "FN_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop view v_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object VIEW "V_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop table test2 + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST2" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop index test1_id + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST1_ID" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_RECORD_VERSION drop index test2_x + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST2_X" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop procedure sp_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_TEST" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop procedure sp_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_WORKER" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop function fn_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object FUNCTION "FN_WORKER" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop view v_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object VIEW "V_TEST" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop table test2 + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST2" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop index test1_id + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST1_ID" is in use + (335544345, 335544351, 335544453) + + SNAPSHOT drop index test2_x + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST2_X" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop procedure sp_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_TEST" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop procedure sp_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_WORKER" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop function fn_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object FUNCTION "FN_WORKER" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop view v_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object VIEW "V_TEST" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop table test2 + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST2" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop index test1_id + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST1_ID" is in use + (335544345, 335544351, 335544453) + + SERIALIZABLE drop index test2_x + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST2_X" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop procedure sp_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop procedure sp_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object PROCEDURE "SP_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop function fn_worker + lock conflict on no wait transaction + -unsuccessful metadata update + -object FUNCTION "FN_WORKER" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop view v_test + lock conflict on no wait transaction + -unsuccessful metadata update + -object VIEW "V_TEST" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop table test2 + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST2" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop index test1_id + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST1_ID" is in use + (335544345, 335544351, 335544453) + + READ_COMMITTED_READ_CONSISTENCY drop index test2_x + lock conflict on no wait transaction + -unsuccessful metadata update + -object INDEX "TEST2_X" is in use + (335544345, 335544351, 335544453) + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From a53cc7ffadb5f2d44a327296a66330b399166714 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 23 Aug 2024 12:48:43 +0300 Subject: [PATCH 0143/1064] Added/Updated tests\bugs\core_1254_test.py: Reimplemented in order to have same results regardless on OptimizeForFirstRows = true / false --- tests/bugs/core_1254_test.py | 109 +++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 29 deletions(-) diff --git a/tests/bugs/core_1254_test.py b/tests/bugs/core_1254_test.py index 3681445c..06533df9 100644 --- a/tests/bugs/core_1254_test.py +++ b/tests/bugs/core_1254_test.py @@ -2,52 +2,103 @@ """ ID: issue-1678 -ISSUE: 1678 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1678 TITLE: Problem with DISTINCT and insensitive collations -DESCRIPTION: +DESCRIPTION: See https://github.com/FirebirdSQL/firebird/issues/2965 JIRA: CORE-1254 FBTEST: bugs.core_1254 +NOTES: + 1. Confirmed problem on 2.1.3.18185 + Both queries: 'select ... group by ...' and 'select distinct ...' issued six rows: + GROUP_ID QUESTION + ======== ============ + a 1 + a 2 + a 3 + A 1 + A 2 + A 3 + (instead of expected three rows with 'a' or 'A' in the 1st column). + The only correct result issued when index was used. + + 2. Values in 1st column can vary if OptimizeForFirstRows = true (FB 5.x+). + Because of this, we have to check only COUNT of letters in this column + that are unique being compared using case SENSITIVE collation. + In all cases (for queries and with/without index) this count must be 1. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE TEST -(GROUP_ID VARCHAR(1) CHARACTER SET UTF8 COLLATE UNICODE_CI, -QUESTION INTEGER, -SCORE INTEGER); -COMMIT; -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('a',1,1); -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('a',2,1); -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('a',3,1); -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('A',1,1); -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('A',2,1); -INSERT INTO TEST (GROUP_ID,QUESTION,SCORE) VALUES ('A',3,1); -COMMIT; - +init_script = """ + create table test( + group_id varchar(1) character set utf8 collate unicode_ci, + question integer, + score integer + ); + commit; + insert into test (group_id,question,score) values ('a',1,11); + insert into test (group_id,question,score) values ('a',3,13); + insert into test (group_id,question,score) values ('A',1,14); + insert into test (group_id,question,score) values ('a',2,12); + insert into test (group_id,question,score) values ('A',2,15); + insert into test (group_id,question,score) values ('A',3,16); + commit; + -- See https://github.com/FirebirdSQL/firebird/issues/2965#issue-866882047 + -- GROUP BY will use an index on multi-byte or insensitive collation only + -- when this index is: 1) UNIQUE and 2) ASCENDING. + create UNIQUE index test_gr_que_score on test(group_id, question, score); + commit; """ + db = db_factory(charset='UTF8', init=init_script) -test_script = """SELECT GROUP_ID, QUESTION, SUM(SCORE) FROM TEST GROUP BY 1,2; -SELECT DISTINCT GROUP_ID, QUESTION FROM TEST;""" +test_script = """ + --set explain on; + --set plan on; + set list on; + alter index test_gr_que_score inactive; + commit; + + select count( + distinct cast( group_id as varchar(1) + -- Check count of unique values in 1st column using + -- case SENSITIVE collation: + -- ######################### + character set ascii + ) + ) as "case_SENSITIVE_distinct_gr_1" + from ( + select group_id, question from test group by 1,2 + ); -act = isql_act('db', test_script) + select count( distinct cast(group_id as varchar(1) character set ascii)) as "case_SENSITIVE_distinct_gr_2" + from ( + select distinct group_id, question from test + ); -expected_stdout = """ -GROUP_ID QUESTION SUM -======== ============ ===================== -a 1 2 -a 2 2 -a 3 2 + alter index test_gr_que_score active; + commit; + select count( distinct cast(group_id as varchar(1) character set ascii)) as "case_SENSITIVE_distinct_gr_3" + from ( + select group_id, question from test group by 1,2 + ); -GROUP_ID QUESTION -======== ============ -a 1 -a 2 -a 3 + select count( distinct cast(group_id as varchar(1) character set ascii)) as "case_SENSITIVE_distinct_gr_4" + from ( + select distinct group_id, question from test + ); +""" + +act = isql_act('db', test_script) +expected_stdout = """ + case_SENSITIVE_distinct_gr_1 1 + case_SENSITIVE_distinct_gr_2 1 + case_SENSITIVE_distinct_gr_3 1 + case_SENSITIVE_distinct_gr_4 1 """ @pytest.mark.version('>=3') From 01a2478ad27689580d6e1384362484c833858597 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 23 Aug 2024 15:01:07 +0300 Subject: [PATCH 0144/1064] Added/Updated tests\bugs\core_1292_test.py: Reimplemented because of fail if we change OptimizeForFirstRows = true config parameter. See notes. --- tests/bugs/core_1292_test.py | 164 ++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 71 deletions(-) diff --git a/tests/bugs/core_1292_test.py b/tests/bugs/core_1292_test.py index db9874a1..1384f6b4 100644 --- a/tests/bugs/core_1292_test.py +++ b/tests/bugs/core_1292_test.py @@ -7,56 +7,51 @@ DESCRIPTION: JIRA: CORE-1292 FBTEST: bugs.core_1292 +NOTES: + [23.08.2024] pzotov + 1. Removed LIST() from initial query because it displays tokens in unpredictable order. + This can cause fail if we change OptimizeForFirstRows = true config parameter. + 2. Found oddities when try to use non-ascii user name and substitute it using f-notation: + at least REVOKE and GRANT commands reflect this user name in the trace as encoded + in cp1251 instead of utf8. This causes: + 335544321 : arithmetic exception, numeric overflow, or string truncation + 335544565 : Cannot transliterate character between character sets + To be investigated further. """ - +import locale import pytest from firebird.qa import * -db = db_factory(charset='UTF8') - -test_script = """ - set wng off; - - -- Drop old account if it remains from prevoius run: - set term ^; - execute block as - begin - begin - execute statement 'drop user Nebuchadnezzar2_King_of_Babylon' with autonomous transaction; - when any do begin end - end - end^ - set term ;^ - commit; - - - create user Nebuchadnezzar2_King_of_Babylon password 'guinness'; -- revoke admin role; - -- 1234567890123456789012345678901 - -- 1 2 3 - commit; - revoke all on all from Nebuchadnezzar2_King_of_Babylon; - set term ^; - execute block as - begin - if ( rdb$get_context('SYSTEM', 'ENGINE_VERSION') not starting with '2.5' ) then - begin - execute statement 'grant create table to Nebuchadnezzar2_King_of_Babylon'; - end - end - ^ - set term ;^ - commit; - - connect '$(DSN)' user 'Nebuchadnezzar2_King_of_Babylon' password 'guinness'; - - create table test(n int); - commit; - - connect '$(DSN)' user 'SYSDBA' password 'masterkey'; - - set list on; - select usr_name, grantor, can_grant, tab_name,usr_type,obj_type, list(priv) priv_list - from ( +db = db_factory(charset = 'utf8') + +act = python_act('db', substitutions = [ ('[ \t]+', ' '), ]) +tmp_user = user_factory('db', name='Nebuchadnezzar_The_Babylon_Lord', password='123', plugin = 'Srp') +#tmp_user = user_factory('db', name='"НавохудоносорВластелинВавилона2"', password='123', plugin = 'Srp') + +@pytest.mark.version('>=3') +def test_1(act: Action, tmp_user: User, capsys): + + test_sql = f""" + set bail on; + set list on; + set wng off; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + revoke all on all from {tmp_user.name}; + grant create table to {tmp_user.name}; + commit; + + connect '{act.db.dsn}' user {tmp_user.name} password '{tmp_user.password}'; + + select a.mon$user as who_am_i, c.rdb$character_set_name as my_connection_charset + from mon$attachments a + join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + where a.mon$attachment_id = current_connection; + + create table test(n int); + commit; + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + select p.rdb$user usr_name ,p.rdb$grantor grantor @@ -66,31 +61,58 @@ ,p.rdb$object_type obj_type ,trim(p.rdb$privilege) priv from rdb$user_privileges p - where upper(trim(p.rdb$relation_name)) = upper('test') - order by priv - ) - group by usr_name, grantor, can_grant, tab_name,usr_type,obj_type; - commit; - - drop user Nebuchadnezzar2_King_of_Babylon; - commit; -""" - -act = isql_act('db', test_script, substitutions=[('PRIV_LIST.*', '')]) + where + upper(trim(p.rdb$relation_name)) = upper('test') + and p.rdb$user = _utf8 '{tmp_user.name}' collate unicode_ci + order by priv; + commit; + """ + + expected_stdout = f""" + WHO_AM_I {tmp_user.name.upper()} + MY_CONNECTION_CHARSET UTF8 + + USR_NAME {tmp_user.name.upper()} + GRANTOR {tmp_user.name.upper()} + CAN_GRANT 1 + TAB_NAME TEST + USR_TYPE 8 + OBJ_TYPE 0 + PRIV D + + USR_NAME {tmp_user.name.upper()} + GRANTOR {tmp_user.name.upper()} + CAN_GRANT 1 + TAB_NAME TEST + USR_TYPE 8 + OBJ_TYPE 0 + PRIV I + + USR_NAME {tmp_user.name.upper()} + GRANTOR {tmp_user.name.upper()} + CAN_GRANT 1 + TAB_NAME TEST + USR_TYPE 8 + OBJ_TYPE 0 + PRIV R + + USR_NAME {tmp_user.name.upper()} + GRANTOR {tmp_user.name.upper()} + CAN_GRANT 1 + TAB_NAME TEST + USR_TYPE 8 + OBJ_TYPE 0 + PRIV S + + USR_NAME {tmp_user.name.upper()} + GRANTOR {tmp_user.name.upper()} + CAN_GRANT 1 + TAB_NAME TEST + USR_TYPE 8 + OBJ_TYPE 0 + PRIV U + """ -expected_stdout = """ - USR_NAME NEBUCHADNEZZAR2_KING_OF_BABYLON - GRANTOR NEBUCHADNEZZAR2_KING_OF_BABYLON - CAN_GRANT 1 - TAB_NAME TEST - USR_TYPE 8 - OBJ_TYPE 0 - D,I,R,S,U -""" - -@pytest.mark.version('>=3') -def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.isql(switches = ['-q'], input = test_sql, charset = 'utf8', connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout - From 0417933393d61c8621ecb157f9a1ae861ddabb6f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 23 Aug 2024 15:43:59 +0300 Subject: [PATCH 0145/1064] Added/Updated tests\bugs\core_1453_test.py: Reimplemented: we have to avoid to show result of LIST() call because unpredictable order of its tokens. This can cause fail if we change OptimizeForFirstRows = true config parameter. --- tests/bugs/core_1453_test.py | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_1453_test.py b/tests/bugs/core_1453_test.py index fb710faa..54f1a017 100644 --- a/tests/bugs/core_1453_test.py +++ b/tests/bugs/core_1453_test.py @@ -7,45 +7,45 @@ DESCRIPTION: JIRA: CORE-1443 FBTEST: bugs.core_1453 +NOTES: + [23.08.2024] pzotov + Reimplemented: we have to avoid to show result of LIST() call because unpredictable order of its tokens. + This can cause fail if we change OptimizeForFirstRows = true config parameter. + Instead, test apply char_len() to the result of list(<...>, ). """ import pytest from firebird.qa import * -init_script = """CREATE TABLE T1 (ID INTEGER, NAME CHAR(20)); -COMMIT; -INSERT INTO T1 (ID,NAME) VALUES (1,'ORANGE'); -INSERT INTO T1 (ID,NAME) VALUES (1,'APPLE'); -INSERT INTO T1 (ID,NAME) VALUES (1,'LEMON'); -INSERT INTO T1 (ID,NAME) VALUES (2,'ORANGE'); -INSERT INTO T1 (ID,NAME) VALUES (2,'APPLE'); -INSERT INTO T1 (ID,NAME) VALUES (2,'PEAR'); -COMMIT; +init_script = """ + create table t1 (id integer, name char(20)); + commit; + insert into t1 (id,name) values (1,'orange'); + insert into t1 (id,name) values (1,'apple'); + insert into t1 (id,name) values (1,'lemon'); + insert into t1 (id,name) values (2,'orange'); + insert into t1 (id,name) values (2,'apple'); + insert into t1 (id,name) values (2,'pear'); + commit; """ db = db_factory(init=init_script) -test_script = """select ID, LIST( trim(NAME), ASCII_CHAR(35) ) -from T1 -group by 1; +test_script = """ + set list on; + select id, char_length(list( trim(name), ascii_char(35) )) chr_len + from t1 + group by id + order by id; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [ ('[ \t]+', ' '), ]) expected_stdout = """ - ID LIST -============ ================= - 1 0:1 -============================================================================== -LIST: -ORANGE#LEMON#APPLE -============================================================================== - 2 0:2 -============================================================================== -LIST: -PEAR#ORANGE#APPLE -============================================================================== - + ID 1 + CHR_LEN 18 + ID 2 + CHR_LEN 17 """ @pytest.mark.version('>=2.5.0') From 9f45c1f71367b1de5ecc7a708f197ef9a5c61082 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 23 Aug 2024 16:10:30 +0300 Subject: [PATCH 0146/1064] Added/Updated tests\bugs\core_2922_test.py: added second column to 'order by' clause to force predicable output because of possible changing 'OptimizeForFirstRows' config parameter. --- tests/bugs/core_2922_test.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_2922_test.py b/tests/bugs/core_2922_test.py index 5b1424ad..469d0cc1 100644 --- a/tests/bugs/core_2922_test.py +++ b/tests/bugs/core_2922_test.py @@ -41,24 +41,22 @@ join rdb$types rt on rd.rdb$depended_on_type = rt.rdb$type and rt.rdb$type_name containing upper('COLLATION') - order by 1; - + order by dep_name, dep_on + ; """ act = isql_act('db', test_script) expected_stdout = """ -DEP_NAME P1 -DEP_ON WIN1250 -DEP_ON_TYPE COLLATION - -DEP_NAME P1 -DEP_ON UTF8 -DEP_ON_TYPE COLLATION - -DEP_NAME P2 -DEP_ON WIN1250 -DEP_ON_TYPE COLLATION + DEP_NAME P1 + DEP_ON UTF8 + DEP_ON_TYPE COLLATION + DEP_NAME P1 + DEP_ON WIN1250 + DEP_ON_TYPE COLLATION + DEP_NAME P2 + DEP_ON WIN1250 + DEP_ON_TYPE COLLATION """ @pytest.mark.version('>=3.0') From 3626071f72fbc6c11e1a0562155a29e0a901f421 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 23 Aug 2024 22:56:18 +0300 Subject: [PATCH 0147/1064] Added/Updated tests\bugs\gh_8225_test.py: Checked on 5.0.2.1482-604555f. NOT: parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. --- tests/bugs/gh_8225_test.py | 110 +++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 tests/bugs/gh_8225_test.py diff --git a/tests/bugs/gh_8225_test.py b/tests/bugs/gh_8225_test.py new file mode 100644 index 00000000..e923eaee --- /dev/null +++ b/tests/bugs/gh_8225_test.py @@ -0,0 +1,110 @@ +#coding:utf-8 + +""" +ID: issue-8225 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8225 +TITLE: Problematic queries when SubQueryConversion = true +DESCRIPTION: +NOTES: + [23.08.2024] pzotov + 1. Explained plan output temporary disabled: there is question about missed(?) indentation after 'Refetch'. + Sent letter to dimitr, 23.08.2024 21:42. + 2. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + + Confirmed bug on 5.0.2.1479-adfe97a. + Checked on 5.0.2.1482-604555f. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect + +init_script = """ + create domain dm_emp_id smallint; + create domain dm_dep_id smallint; + create domain dm_name varchar(20); + + create table department ( + dept_no dm_dep_id not null + ,dept_name dm_name not null + ); + + create table employee ( + emp_no dm_emp_id not null + ,last_name dm_name not null + ,dept_no dm_dep_id not null + ,constraint emp_key primary key (emp_no) + ); + commit; + insert into department( dept_no, dept_name) values (1, 'd1'); + insert into department( dept_no, dept_name) values (2, 'd2'); + insert into department( dept_no, dept_name) values (3, 'd3'); + insert into employee( emp_no, last_name, dept_no) values (1, 'e1', 1); + insert into employee( emp_no, last_name, dept_no) values (2, 'e2', 2); + insert into employee( emp_no, last_name, dept_no) values (3, 'e3', 3); + insert into employee( emp_no, last_name, dept_no) values (4, 'e4', 1); + insert into employee( emp_no, last_name, dept_no) values (5, 'e5', 1); + insert into employee( emp_no, last_name, dept_no) values (6, 'e6', 1); + insert into employee( emp_no, last_name, dept_no) values (7, 'e7', 2); + insert into employee( emp_no, last_name, dept_no) values (8, 'e8', 3); + insert into employee( emp_no, last_name, dept_no) values (9, 'e9', 3); + commit; + + update department d set dept_no = -dept_no where exists(select * from employee e where e.dept_no = d.dept_no) rows 1; + insert into employee( emp_no, last_name, dept_no) values (12, 'e12', -(select max(dept_no)+1 from department) ); + commit; +""" + +db = db_factory(init=init_script) + +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,<6') +def test_1(act: Action, capsys): + + test_sql = """ + select d.dept_no, d.dept_name from department d + where exists(select * from employee e where e.dept_no = d.dept_no) + order by dept_no rows 1 + """ + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_8225_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_8225_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + # temporary, until question with indentation will be solved by dimitr -- print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + for r in cur.execute(ps): + print(r[0],r[1]) + con.rollback() + + act.expected_stdout = f""" + SubQueryConversion true + 2 d2 + SubQueryConversion false + 2 d2 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From a16a65ddfa2d7b5d4704eebbcd09283c7ce904af Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 26 Aug 2024 14:35:21 +0300 Subject: [PATCH 0148/1064] Added/Updated tests\bugs\gh_8231_test.py: Checked on 5.0.2.1485-274af35 -- all ok. --- tests/bugs/gh_8231_test.py | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/bugs/gh_8231_test.py diff --git a/tests/bugs/gh_8231_test.py b/tests/bugs/gh_8231_test.py new file mode 100644 index 00000000..3ac420cc --- /dev/null +++ b/tests/bugs/gh_8231_test.py @@ -0,0 +1,98 @@ +#coding:utf-8 + +""" +ID: issue-8231 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8231 +TITLE: SubQueryConversion = true --request size limit exceeded / Unsuccessful execution caused by an unavailable resource. unable to allocate memory from operating system +DESCRIPTION: +NOTES: + [26.08.2024] pzotov + Two tables must be joined by columns which has different charset or collates. + Confirmed bug on 5.0.2.1484-3cdfd38 (25.08.2024), got: + Statement failed, SQLSTATE = HY000 + request size limit exceeded + Checked on 5.0.2.1485-274af35 -- all ok. + + Thanks to dimitr for the advice on implementing the test. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect + +init_script = """ + create table t1(fld varchar(10) character set win1252); + create table t2(fld varchar(10) character set utf8); + + insert into t1(fld) values('Ð'); + insert into t2(fld) values('Ð'); + commit; +""" + +db = db_factory(init=init_script) + +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,<6') +def test_1(act: Action, capsys): + + test_sql = """ + select 1 as x + from t1 + where exists (select 1 from t2 where t1.fld = t2.fld) + """ + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_8231_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_8231_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # Print data: + for r in cur.execute(ps): + print(r[0]) + con.rollback() + + act.expected_stdout = f""" + SubQueryConversion true + Select Expression + ....-> Nested Loop Join (semi) + ........-> Table "T1" Full Scan + ........-> Filter + ............-> Table "T2" Full Scan + 1 + + SubQueryConversion false + Sub-query + ....-> Filter + ........-> Table "T2" Full Scan + Select Expression + ....-> Filter + ........-> Table "T1" Full Scan + 1 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 99ceae14eaeb15dd89bd8a16ebb9ad6bfbfdb66d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 26 Aug 2024 23:46:15 +0300 Subject: [PATCH 0149/1064] Added/Updated tests\bugs\core_5229_test.py: added comments about unable to fully turn off IPv6 on Windows. --- tests/bugs/core_5229_test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/bugs/core_5229_test.py b/tests/bugs/core_5229_test.py index a3a69e44..4a3e48ce 100644 --- a/tests/bugs/core_5229_test.py +++ b/tests/bugs/core_5229_test.py @@ -20,6 +20,18 @@ External Data Source provider 'inet6://[' not found ======== It was fixed in gh-8156. + 3. On Windows there is no way to make IPv6 'fully disabled': address '::1' remains active. + According to https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows + "You cannot completely disable IPv6 as IPv6 is used internally on the system for many TCPIP tasks. + For example, you will still be able to run ping ::1 after configuring this setting" + + We can turn off listening of '::1' by FB server if do following: + * run PowerShell and type there: Enable-NetAdapterBinding -Name "*" -ComponentID ms_tcpip6 + * chcp 65001, then: ipconfig /all | findstr /i /r /c:" IPv6.*(preferred)" + * save somewhere IPv6 address from previous command (e.g. 'fe80::f53c:9ecf:aad:4761%14') + * change in firebird.conf: RemoteBindAddress = fe80::f53c:9ecf:aad:4761 + But this requires RESTART of FB server thus cannot be used in QA. + Discussed with Vlad 13-jun-2024. [14.06.2024] pzotov Checked "on external 'inet6://[::1]/{act.db.db_path}'" after fixed GH-8156, builds: 3.0.12.33757, 4.0.5.3112, 5.0.1.1416, 6.0.0.374 From 75eb296c15f9fb52dc619f5e52467bbf45f0f6cf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 27 Aug 2024 09:19:23 +0300 Subject: [PATCH 0150/1064] Added/Updated tests\bugs\gh_8223_test.py: Checked on 5.0.2.1483-0bf2de0 --- tests/bugs/gh_8223_test.py | 140 +++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tests/bugs/gh_8223_test.py diff --git a/tests/bugs/gh_8223_test.py b/tests/bugs/gh_8223_test.py new file mode 100644 index 00000000..d5017dff --- /dev/null +++ b/tests/bugs/gh_8223_test.py @@ -0,0 +1,140 @@ +#coding:utf-8 + +""" +ID: issue-8223 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8223 +TITLE: SubQueryConversion = true: error "no current record for fetch operation" with complex joins +DESCRIPTION: +NOTES: + [27.08.2024] pzotov + 1. Confirmed bug on 5.0.1.1469-1d792e4 (Release (15.08.2024), got for SubQueryConversion=true: + no current record for fetch operation / gdscode = 335544348. + + 2. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + 3. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + + Checked on 5.0.2.1483-0bf2de0 -- all ok. + Thanks to dimitr for the advice on implementing the test. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError + +init_script = """ + create table t1(id int); + create table t2(id int); + create table t3(id int); + create table t4(id int); + create table t5(id int); + + insert into t1(id) values(1); + insert into t2(id) values(1); + insert into t3(id) values(1); + insert into t4(id) values(1); + insert into t5(id) values(1); + commit; + + create view v as + select a.id as a_id, b.id as b_id, c.id as c_id + from t1 a + left join t2 b on a.id = b.id + left join t3 c on b.id = c.id; + commit; +""" + +db = db_factory(init=init_script) + +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,<6') +def test_1(act: Action, capsys): + + test_sql = """ + select v.a_id, v.b_id, v.c_id + from v + join t4 d on v.c_id = d.id + where exists ( + select 1 + from t5 e where e.id = d.id + ) + """ + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_8223_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_8223_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # Print data: + for r in cur.execute(ps): + print(r[0], r[1], r[2]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + act.expected_stdout = f""" + SubQueryConversion true + Select Expression + ....-> Filter + ........-> Hash Join (semi) + ............-> Filter + ................-> Hash Join (inner) + ....................-> Nested Loop Join (outer) + ........................-> Nested Loop Join (outer) + ............................-> Table "T1" as "V A" Full Scan + ............................-> Filter + ................................-> Table "T2" as "V B" Full Scan + ........................-> Filter + ............................-> Table "T3" as "V C" Full Scan + ....................-> Record Buffer (record length: 25) + ........................-> Table "T4" as "D" Full Scan + ............-> Record Buffer (record length: 25) + ................-> Table "T5" as "E" Full Scan + 1 1 1 + SubQueryConversion false + Sub-query + ....-> Filter + ........-> Table "T5" as "E" Full Scan + Select Expression + ....-> Filter + ........-> Hash Join (inner) + ............-> Nested Loop Join (outer) + ................-> Nested Loop Join (outer) + ....................-> Table "T1" as "V A" Full Scan + ....................-> Filter + ........................-> Table "T2" as "V B" Full Scan + ................-> Filter + ....................-> Table "T3" as "V C" Full Scan + ............-> Record Buffer (record length: 25) + ................-> Filter + ....................-> Table "T4" as "D" Full Scan + 1 1 1 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From e06829557f8a3b50ed5d6229fceae8a7a67a2ace Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 28 Aug 2024 16:45:00 +0300 Subject: [PATCH 0151/1064] Added/Updated tests\bugs\gh_8233_test.py: Checked on 5.0.2.1487-6934878 -- all ok. --- tests/bugs/gh_8233_test.py | 117 +++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/bugs/gh_8233_test.py diff --git a/tests/bugs/gh_8233_test.py b/tests/bugs/gh_8233_test.py new file mode 100644 index 00000000..035df828 --- /dev/null +++ b/tests/bugs/gh_8233_test.py @@ -0,0 +1,117 @@ +#coding:utf-8 + +""" +ID: issue-8233 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8233 +TITLE: SubQueryConversion = true --multiple rows in singleton select +DESCRIPTION: +NOTES: + [27.08.2024] pzotov + 1. Confirmed bug on 5.0.1.1485-274af35 (26.08.2024), got for SubQueryConversion=true: + "multiple rows in singleton select", gdscodes: (335544652, 335544842) + 2. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + 3. Table 't1' must have more than one row for bug reproducing. Query must be enclosed in execute block. + 4. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + + Checked on 5.0.2.1487-6934878 -- all ok. + Thanks to dimitr for the advice on implementing the test. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError + +init_script = """ +create table t1(id int, fld int); +create table t2(id int, fld int); + +insert into t1(id, fld) values(1, 111); +insert into t1(id, fld) values(2, 222); +insert into t1(id, fld) values(3, 333); +insert into t2(id, fld) values(3, 999); +commit; +""" + +db = db_factory(init=init_script) + +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,<6') +def test_1(act: Action, capsys): + + test_sql = """ + execute block returns (res int) + as + begin + select first 1 id from t1 + where exists (select 1 from t2 where t1.id = t2.id) + order by t1.id + into :res; + suspend; + end + """ + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_8233_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_8233_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # Print data: + for r in cur.execute(ps): + print(r[0]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + act.expected_stdout = f""" + SubQueryConversion true + Select Expression (line 5, column 12) + ....-> Singularity Check + ........-> First N Records + ............-> Filter + ................-> Hash Join (semi) + ....................-> Sort (record length: 28, key length: 8) + ........................-> Table "T1" Full Scan + ....................-> Record Buffer (record length: 25) + ........................-> Table "T2" Full Scan + 3 + SubQueryConversion false + Sub-query + ....-> Filter + ........-> Table "T2" Full Scan + Select Expression (line 5, column 12) + ....-> Singularity Check + ........-> First N Records + ............-> Sort (record length: 28, key length: 8) + ................-> Filter + ....................-> Table "T1" Full Scan + 3 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 9f489646743686cd38c55b0dc77dd9016ca5c741 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 29 Aug 2024 21:21:49 +0300 Subject: [PATCH 0152/1064] Increased StatementTimeout. It seems that in some cases previous value was too small --- configs/fb40_all.conf | 2 +- configs/fb50_all.conf | 5 ++++- configs/fb60_all.conf | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/configs/fb40_all.conf b/configs/fb40_all.conf index 103e7311..80ea8205 100644 --- a/configs/fb40_all.conf +++ b/configs/fb40_all.conf @@ -68,7 +68,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 300 +StatementTimeout = 600 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 diff --git a/configs/fb50_all.conf b/configs/fb50_all.conf index a811cdcd..850fcda1 100644 --- a/configs/fb50_all.conf +++ b/configs/fb50_all.conf @@ -70,7 +70,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 300 +StatementTimeout = 600 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 @@ -81,3 +81,6 @@ TipCacheBlockSize = 4M # Added 03-apr-2023: ParallelWorkers = 1 MaxParallelWorkers = 8 + +# SubQueryConversion = false +# OptimizeForFirstRows = false diff --git a/configs/fb60_all.conf b/configs/fb60_all.conf index ebb4196a..679b1edd 100644 --- a/configs/fb60_all.conf +++ b/configs/fb60_all.conf @@ -70,7 +70,7 @@ MaxIdentifierByteLength = 252 MaxIdentifierCharLength = 63 WireCryptPlugin = ChaCha, Arc4 -StatementTimeout = 300 +StatementTimeout = 600 ConnectionIdleTimeout = 0 ClearGTTAtRetaining = 0 @@ -81,3 +81,5 @@ TipCacheBlockSize = 4M # Added 03-apr-2023: ParallelWorkers = 1 MaxParallelWorkers = 8 + +#OptimizeForFirstRows = false From 92df06e66d2c5616e0a06e09c3fce8ac658cd41b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 31 Aug 2024 22:00:49 +0300 Subject: [PATCH 0153/1064] Added/Updated tests\functional\tabloid\test_657d86fe.py: Checked on 6.0.0.4444, 5.0.2.1487, 4.0.6.3142 --- tests/functional/tabloid/test_657d86fe.py | 72 +++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/functional/tabloid/test_657d86fe.py diff --git a/tests/functional/tabloid/test_657d86fe.py b/tests/functional/tabloid/test_657d86fe.py new file mode 100644 index 00000000..1bf357a3 --- /dev/null +++ b/tests/functional/tabloid/test_657d86fe.py @@ -0,0 +1,72 @@ +#coding:utf-8 + +""" +ID: None +ISSUE: https://github.com/FirebirdSQL/firebird/commit/657d86fed65e647dc162980836d24a2e19c1342c +TITLE: RemoteAuxPort is per-database +DESCRIPTION: + Test checks ability to set value of free port in DPB for RemoteAuxPort parameter. + This is done two times with verifying that value is actually changed by querying to rdb$config. +NOTES: + [31.08.2024] pzotov + 1. No ticket has been created for this test. + 2. Custom driver-config object must be used for DPB. + + Checked on 6.0.0.4444, 5.0.2.1487, 4.0.6.3142 +""" + +import socket +from contextlib import closing +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError + +db = db_factory() +act = python_act('db') + +#----------------------------------------------------------- + +def find_free_port(): + # AF_INET - constant represent the address (and protocol) families, used for the first argument to socket() + # A pair (host, port) is used for the AF_INET address family, where host is a string representing either a + # hostname in Internet domain notation like 'daring.cwi.nl' or an IPv4 address like '100.50.200.5', and port is an integer. + # SOCK_STREAM means that it is a TCP socket. + # SOCK_DGRAM means that it is a UDP socket. + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: + s.bind(('', 0)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + free_port = s.getsockname()[1] + return free_port + +#----------------------------------------------------------- + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + for iter in range(2): + free_aux_port = find_free_port() + srv_cfg = driver_config.register_server(name = f'srv_cfg_657d86fe_{iter}', config = '') + db_cfg_name = f'db_cfg_657d86fe_{iter}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + RemoteAuxPort = {free_aux_port} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'RemoteAuxPort'") + for r in cur: + print(iter, r[0], r[1]) + + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + act.expected_stdout = f""" + {iter} RemoteAuxPort {free_aux_port} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 207c9dacfb48e9e821cebd062a4fe7f359f9b88b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 1 Sep 2024 10:51:09 +0300 Subject: [PATCH 0154/1064] Added/Updated tests\bugs\gh_6282_test.py: On Linux argument of tzfile is shown with prefix, e.g. '/usr/share/zoneinfo/', so we have to remove it --- tests/bugs/gh_6282_test.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_6282_test.py b/tests/bugs/gh_6282_test.py index aa25b771..a38abf20 100644 --- a/tests/bugs/gh_6282_test.py +++ b/tests/bugs/gh_6282_test.py @@ -20,6 +20,13 @@ or AttributeError: 'iUtil_v2' object has no attribute 'decode_timestamp_tz' + [01.09.2024] + On Linux argument of tzfile is shown with prefix ("/usr/share/zoneinfo/"), so we have to remove it: + : + Windows = tzfile('Indian/Cocos') + Linux = tzfile('/usr/share/zoneinfo/Indian/Cocos') + This is done by extracting '_timezone_' property of this instance. + Checked on 6.0.0.396, 5.0.1.1440, 4.0.5.3127 """ import pytest @@ -104,7 +111,7 @@ def test_1(act: Action, capsys): cur = con.cursor() cur.execute('select current_timestamp from rdb$database') for r in cur: - print(r[0].tzinfo) + print(r[0].tzinfo._timezone_) cur.close() # The value set through the DPB should survive an `alter session reset` @@ -114,11 +121,14 @@ def test_1(act: Action, capsys): cur = con.cursor() cur.execute('select current_timestamp from rdb$database') for r in cur: - print(r[0].tzinfo) - + # class 'dateutil.zoneinfo.tzfile' + tzfile_nfo = r[0].tzinfo # : Windows = tzfile('Indian/Cocos'); Linux = tzfile('/usr/share/zoneinfo/Indian/Cocos') + # tzfile_arg = tzfile_nfo._filename # : Windows = 'Indian/Cocos'; Linux = '/usr/share/zoneinfo/Indian/Cocos' + print(tzfile_nfo._timezone_) # Windows: 'Indian/Cocos'; Linux: 'Indian/Cocos' + act.expected_stdout = f""" - tzfile('{SELECTED_TIMEZONE}') - tzfile('{SELECTED_TIMEZONE}') + {SELECTED_TIMEZONE} + {SELECTED_TIMEZONE} """ act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 0f8d782ff41eeb5ff1d4fedd42876ad01869cf37 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Sep 2024 00:47:33 +0300 Subject: [PATCH 0155/1064] Added/Updated tests\functional\tabloid\test_3b372197.py: Checked on 6.0.0.446, 5.0.2.1487 --- tests/functional/tabloid/test_3b372197.py | 194 ++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 tests/functional/tabloid/test_3b372197.py diff --git a/tests/functional/tabloid/test_3b372197.py b/tests/functional/tabloid/test_3b372197.py new file mode 100644 index 00000000..2e4e7ae1 --- /dev/null +++ b/tests/functional/tabloid/test_3b372197.py @@ -0,0 +1,194 @@ +#coding:utf-8 + +""" +ID: None +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6798 +TITLE: built-in functions UNICODE_CHAR and UNICODE_VAL +DESCRIPTION: + Test verifies ability to call UNICODE_CHAR/UNICODE_VAL for each code point + in Unicode ranges defined in https://jrgraphix.net/r/Unicode/, except following: + (0xD800, 0xDB7F), # High Surrogates + (0xDB80, 0xDBFF), # High Private Use Surrogates + (0xDC00, 0xDFFF), # Low Surrogates + Result of UNICODE_VAL(UNICODE_CHAR()) must be for all code points. + Commit in FB 5.x (14-may-2021): + https://github.com/FirebirdSQL/firebird/commit/3b372197e4bec60842a7ca974a07546858b6dd30 +NOTES: + [02.09.2024] pzotov + Test duration on Windows: about 205 seconds. + Checked on 6.0.0.446, 5.0.2.1487 +""" +import pytest +from firebird.qa import * + +init_sql = """ + set term ^; + create procedure sp_get_unicode_char(a_code_point int) returns(u char(1) character set utf8) + as + begin + u = unicode_char(a_code_point); + suspend; + end + ^ + create procedure sp_get_unicode_val(u char(1) character set utf8) returns(code_point int) + as + begin + code_point = unicode_val(u); + suspend; + end + ^ + set term ;^ + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +#------------------------------------------------ + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action, capsys): + + # https://jrgraphix.net/r/Unicode/ + UNICODE_RANGES_MAP = { + (0x0020, 0x007F) : 'Basic Latin', + (0x00A0, 0x00FF) : 'Latin-1 Supplement', + (0x0100, 0x017F) : 'Latin Extended-A', + (0x0180, 0x024F) : 'Latin Extended-B', + (0x0400, 0x04FF) : 'Cyrillic', + (0x0500, 0x052F) : 'Cyrillic Supplementary', + (0x0300, 0x036F) : 'Combining Diacritical Marks', + (0x0250, 0x02AF) : 'IPA Extensions', + (0x0370, 0x03FF) : 'Greek and Coptic', + (0x0530, 0x058F) : 'Armenian', + (0x02B0, 0x02FF) : 'Spacing Modifier Letters', + (0x0590, 0x05FF) : 'Hebrew', + (0x0600, 0x06FF) : 'Arabic', + (0x0700, 0x074F) : 'Syriac', + (0x0780, 0x07BF) : 'Thaana', + (0x0900, 0x097F) : 'Devanagari', + (0x0980, 0x09FF) : 'Bengali', + (0x0A00, 0x0A7F) : 'Gurmukhi', + (0x0A80, 0x0AFF) : 'Gujarati', + (0x0B00, 0x0B7F) : 'Oriya', + (0x0B80, 0x0BFF) : 'Tamil', + (0x0C00, 0x0C7F) : 'Telugu', + (0x0C80, 0x0CFF) : 'Kannada', + (0x0D00, 0x0D7F) : 'Malayalam', + (0x0D80, 0x0DFF) : 'Sinhala', + (0x0E00, 0x0E7F) : 'Thai', + (0x0E80, 0x0EFF) : 'Lao', + (0x0F00, 0x0FFF) : 'Tibetan', + (0x1000, 0x109F) : 'Myanmar', + (0x10A0, 0x10FF) : 'Georgian', + (0x1100, 0x11FF) : 'Hangul Jamo', + (0x1200, 0x137F) : 'Ethiopic', + (0x13A0, 0x13FF) : 'Cherokee', + (0x1400, 0x167F) : 'Unified Canadian Aboriginal Syllabics', + (0x1680, 0x169F) : 'Ogham', + (0x16A0, 0x16FF) : 'Runic', + (0x1700, 0x171F) : 'Tagalog', + (0x1720, 0x173F) : 'Hanunoo', + (0x1740, 0x175F) : 'Buhid', + (0x1760, 0x177F) : 'Tagbanwa', + (0x1780, 0x17FF) : 'Khmer', + (0x1800, 0x18AF) : 'Mongolian', + (0x1900, 0x194F) : 'Limbu', + (0x1950, 0x197F) : 'Tai Le', + (0x19E0, 0x19FF) : 'Khmer Symbols', + (0x1D00, 0x1D7F) : 'Phonetic Extensions', + (0x1E00, 0x1EFF) : 'Latin Extended Additional', + (0x1F00, 0x1FFF) : 'Greek Extended', + (0x2000, 0x206F) : 'General Punctuation', + (0x2070, 0x209F) : 'Superscripts and Subscripts', + (0x20A0, 0x20CF) : 'Currency Symbols', + (0x20D0, 0x20FF) : 'Combining Diacritical Marks for Symbols', + (0x2100, 0x214F) : 'Letterlike Symbols', + (0x2150, 0x218F) : 'Number Forms', + (0x2190, 0x21FF) : 'Arrows', + (0x2200, 0x22FF) : 'Mathematical Operators', + (0x2300, 0x23FF) : 'Miscellaneous Technical', + (0x2400, 0x243F) : 'Control Pictures', + (0x2440, 0x245F) : 'Optical Character Recognition', + (0x2460, 0x24FF) : 'Enclosed Alphanumerics', + (0x2500, 0x257F) : 'Box Drawing', + (0x2580, 0x259F) : 'Block Elements', + (0x25A0, 0x25FF) : 'Geometric Shapes', + (0x2600, 0x26FF) : 'Miscellaneous Symbols', + (0x2700, 0x27BF) : 'Dingbats', + (0x27C0, 0x27EF) : 'Miscellaneous Mathematical Symbols-A', + (0x27F0, 0x27FF) : 'Supplemental Arrows-A', + (0x2800, 0x28FF) : 'Braille Patterns', + (0x2900, 0x297F) : 'Supplemental Arrows-B', + (0x2980, 0x29FF) : 'Miscellaneous Mathematical Symbols-B', + (0x2A00, 0x2AFF) : 'Supplemental Mathematical Operators', + (0x2B00, 0x2BFF) : 'Miscellaneous Symbols and Arrows', + (0x2E80, 0x2EFF) : 'CJK Radicals Supplement', + (0x2F00, 0x2FDF) : 'Kangxi Radicals', + (0x2FF0, 0x2FFF) : 'Ideographic Description Characters', + (0x3000, 0x303F) : 'CJK Symbols and Punctuation', + (0x3040, 0x309F) : 'Hiragana', + (0x30A0, 0x30FF) : 'Katakana', + (0x3100, 0x312F) : 'Bopomofo', + (0x3130, 0x318F) : 'Hangul Compatibility Jamo', + (0x3190, 0x319F) : 'Kanbun', + (0x31A0, 0x31BF) : 'Bopomofo Extended', + (0x31F0, 0x31FF) : 'Katakana Phonetic Extensions', + (0x3200, 0x32FF) : 'Enclosed CJK Letters and Months', + (0x3300, 0x33FF) : 'CJK Compatibility', + (0x3400, 0x4DBF) : 'CJK Unified Ideographs Extension A', + (0x4DC0, 0x4DFF) : 'Yijing Hexagram Symbols', + (0x4E00, 0x9FFF) : 'CJK Unified Ideographs', + (0xA000, 0xA48F) : 'Yi Syllables', + (0xA490, 0xA4CF) : 'Yi Radicals', + (0xAC00, 0xD7AF) : 'Hangul Syllables', + (0xE000, 0xF8FF) : 'Private Use Area', + (0xF900, 0xFAFF) : 'CJK Compatibility Ideographs', + (0xFB00, 0xFB4F) : 'Alphabetic Presentation Forms', + (0xFB50, 0xFDFF) : 'Arabic Presentation Forms-A', + (0xFE00, 0xFE0F) : 'Variation Selectors', + (0xFE20, 0xFE2F) : 'Combining Half Marks', + (0xFE30, 0xFE4F) : 'CJK Compatibility Forms', + (0xFE50, 0xFE6F) : 'Small Form Variants', + (0xFE70, 0xFEFF) : 'Arabic Presentation Forms-B', + (0xFF00, 0xFFEF) : 'Halfwidth and Fullwidth Forms', + (0xFFF0, 0xFFFF) : 'Specials', + (0x10000, 0x1007F) : 'Linear B Syllabary', + (0x10080, 0x100FF) : 'Linear B Ideograms', + (0x10100, 0x1013F) : 'Aegean Numbers', + (0x10300, 0x1032F) : 'Old Italic', + (0x10330, 0x1034F) : 'Gothic', + (0x10380, 0x1039F) : 'Ugaritic', + (0x10400, 0x1044F) : 'Deseret', + (0x10450, 0x1047F) : 'Shavian', + (0x10480, 0x104AF) : 'Osmanya', + (0x10800, 0x1083F) : 'Cypriot Syllabary', + (0x1D000, 0x1D0FF) : 'Byzantine Musical Symbols', + (0x1D100, 0x1D1FF) : 'Musical Symbols', + (0x1D300, 0x1D35F) : 'Tai Xuan Jing Symbols', + (0x1D400, 0x1D7FF) : 'Mathematical Alphanumeric Symbols', + (0x20000, 0x2A6DF) : 'CJK Unified Ideographs Extension B', + (0x2F800, 0x2FA1F) : 'CJK Compatibility Ideographs Supplement', + (0xE0000, 0xE007F) : 'Tags', + } + + mismatches = set() + with act.db.connect(charset = 'utf-8') as con: + cur = con.cursor() + for bound_points, range_name in UNICODE_RANGES_MAP.items(): + for code_point in range(bound_points[0],bound_points[1]): + cur.callproc( "sp_get_unicode_char", (code_point,) ) + unicode_chr = cur.fetchone()[0] + cur.callproc( "sp_get_unicode_val", (unicode_chr,) ) + checked_code_point = cur.fetchone()[0] + if checked_code_point == code_point: + pass + else: + mismatches.add( (range_name, code_point, unicode_chr, checked_code_point) ) + + print(len(mismatches)) + for s in mismatches: + print(s) + act.expected_stdout = '0' + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 97343f48138dc19d33a66071b19f8a90b8eb11fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Sep 2024 11:22:00 +0300 Subject: [PATCH 0156/1064] Added/Updated tests\bugs\core_2650_test.py: Fully re-implemented, see notes. Checked on 6.0.0.447-901b4ce, 5.0.2.1487, 4.0.6.3142 --- tests/bugs/core_2650_test.py | 1203 ++++++++++++++++++++-------------- 1 file changed, 701 insertions(+), 502 deletions(-) diff --git a/tests/bugs/core_2650_test.py b/tests/bugs/core_2650_test.py index dfd57df7..2836dea3 100644 --- a/tests/bugs/core_2650_test.py +++ b/tests/bugs/core_2650_test.py @@ -5,26 +5,44 @@ ISSUE: 3057 TITLE: Improve sorting performance when long VARCHARs are involved DESCRIPTION: - Test verifies trivial queries with persistent and computed columns, predicates, views, - expressions without reference to any column and datatypes which have no symmetrical - transformation from value to a key (decfloat, time-with-timezone and varchar with non-default collation). + Test verifies trivial queries with persistent and computed columns, predicates, views, + expressions without reference to any column and datatypes which have no symmetrical + transformation from value to a key (decfloat, time-with-timezone and varchar with non-default collation). - It is supposed that default value of InlineSortThreshold parameter is 1000. - No changes in the firebird.conf reuired. + It is supposed that default value of InlineSortThreshold parameter is 1000. + No changes in the firebird.conf reuired. - This test most probably will be added by some new examples later. - - Thanks to dimitr for lot of explanations (e-mail discussion was 28.12.2020). + This test most probably will be added by some new examples later. + Thanks to dimitr for lot of explanations (e-mail discussion was 28.12.2020). JIRA: CORE-2650 FBTEST: bugs.core_2650 +NOTES: + [02.09.2024] + 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.: + {query_map[1000][0]} // output will be compared with: "select txt_short from test a01 order by id" + {query_map[1000][1]} // output will be compared with: "Must NOT use refetch because length of non-key column is less than threshold" + 2. Explained plans for FB 4.x and 5.x/6.x not equal. + Because of this, expected output is stored differently (fb4x_expected_out, fb5x_expected_out). + 3. Indentation between 'Refetch' and subsequent 'Sort' was removed (only 'master' was affected). + This change was caused by (or related to) profiler, discussed with Adriano. + See letters since 24-aug-2023, subj: + "Test for gh-7687: can't understand the output for trivial .sql (from the ticket)" + See also: + https://groups.google.com/g/firebird-devel/c/dWIgSIemys4/m/TzUWYwmVAQAJ (18-JUL-2023) + https://github.com/FirebirdSQL/firebird/issues/7687 (28-JUL-2023) + 4 Need to preserve indentation was explained by dimitr 28-aug-2024 12:57, subj: + 'Explained plan, "Refetch": should the indentation be after it at line with subsequent "-> Sort (record ...)" ?' + 5. Indentation was restored 01-sep-2024 by fix https://github.com/FirebirdSQL/firebird/issues/8235 + https://github.com/FirebirdSQL/firebird/commit/901b4ced9a3615929e0027d42ebb2392e943b205 + + Checked on 6.0.0.447-901b4ce, 5.0.2.1487, 4.0.6.3142 """ import pytest from firebird.qa import * -db = db_factory() - -test_script = """ +init_sql = """ set bail on; recreate view v_unioned as select 1 id from rdb$database; commit; @@ -42,133 +60,6 @@ ,computed_ts_left computed by( left(txt_short,10) ) ,computed_tb_left computed by( left(txt_broad,10) ) ); - commit; - - set plan on; - set explain on; - -- set echo on; - - --########################## p e r s i s t e n t c o l u m n s ################################## - - -- Must not use refetch because length of non-key column is less than default threshold: - select txt_short from test a01 order by id; - - -- Must USE refetch because length of non-key column is greater than default threshold: - select txt_broad from test a02 order by id; - - -- MUST use refethc regardless on length of column because 'ROWS ' presents (!): - select txt_short from test a03 order by id rows 1; - - - -- ########################## c o m p u t e d c o l u m n s ##################################### - - -- does NOT use refetch because computed column is based on txt_short which has length < threshold: - select id, computed_ts_dup from test order by id; - - -- must use refetch because computed column is based on txt_broad which has length >= threshold: - select id, computed_tb_dup from test order by id; - - -- ###################### p r e d i c a t e s, e x c e p t E X I S T S ######################## - - select id from test a04 where '' in (select txt_short from test x04 where txt_short = '' order by id) ; - - select id from test a05 where '' in (select txt_broad from test x05 where txt_broad = '' order by id) ; - - - select id from test a06 where '' not in (select txt_short from test x06 where txt_short>'' order by id) ; - - select id from test a07 where '' not in (select txt_broad from test x07 where txt_broad>'' order by id) ; - - - select id from test a08 where '' > all (select id from test x08 where txt_short>'' order by id) ; - - select id from test a09 where '' > all (select id from test x09 where txt_broad>'' order by id) ; - - - select id from test a10 where '' <> any (select id from test x10 where txt_short>'' order by id) ; - - select id from test a11 where '' <> any (select id from test x11 where txt_broad>'' order by id) ; - - -- ######################################## e x i s t s ########################################### - - -- Predicate "EXISTS" must turn on refetching regardless of record length, but only when "WHERE" has column which not present in "ORDER BY" - select id,txt_short from test a12 where exists(select 1 from test x12 where txt_short>'' order by id) ; -- MUST use refetch - - -- does NOT use refetch: "order by" list contains the single element: ID, and it is the same field that 'computed_id_dup' relies on. - select id,txt_short from test a13 where exists(select 1 from test x13 where computed_id_dup > 0 order by id) ; - - -- ### NB ### Must use refetch! See letter from dimitr 28.12.2020 14:49, reply for: - -- "select id,txt_short from test a14 where exists(select 1 from test x14 where computed_ts_dup > '' order by computed_ts_left);" - -- 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. - select id,txt_short from test a14 where exists(select 1 from test x14 where computed_id_dup > 0 order by computed_id_dup ) ; - - -- does NOT use refetch: all persistent columns from "WHERE" expr (f01, f02) belongs to "order by" list: - 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 use refetch: one of coulmns from "where" expr (id) does not belong to "order by" list: - 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: computed column in "where" expr does not belong to "order by" list: - select id,txt_short from test a17 where exists(select 1 from test x17 where computed_id_dup > 0 order by f01); - - -- does NOT use refetch: computed column "computed_guid" does not rely on any other columns in the table: - select id,txt_short from test a18 where exists(select 1 from test x18 where computed_guid > '' order by f01); - - - -- must use refetch both in anchor and recursive parts: - 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; - commit; - - - -- ###################################### v i e w s ########################################### - - recreate view v_unioned as - select id, txt_broad from test - union all - select -1, 'qwerty' - from rdb$database rows 0; - - -- does NOT use refetch because view is based on UNION: - select txt_broad from v_unioned v01 order by id; - commit; - - -- ################################# e x p r e s s i o n s ##################################### - - -- 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 left(txt_broad, 50) as txt from test a21 order by id; - - -- does 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 left( txt_short || txt_short, 2000) as txt from test a22 order by id; - commit; - - - -- ########### n o n - s y m m e t r i c a l k e y - v a l u e d a t a t y p e s ######### - - -- Following data types in common case have no ability to get column value from a key: - -- * International type text has a computed key - -- * Different decimal float values sometimes have same keys - -- * Date/time with time zones too. - -- Because of this, a field of any such datatype that is specified in "order by" list, must also be involved - -- in the non-key fields and sort will deal with such "concatenated" list. - -- If total length of such list not exceeds InlineSortThreshold then sort will be done without refetch. - -- Otherwise refetch will occur. - -- See src\\jrd\\opt.cpp, OPT_gen_sort() and explanation fro dimitr: letter 28.12.2020 16:44. recreate table test_ns_01( id decfloat @@ -180,13 +71,6 @@ ,txt_short varchar(982) ); - select * from test_ns_01 a23 order by id; -- must use refetch - - select * from test_ns_02 a24 order by id; -- must NOT use refetch - - commit; - - ------------------------------------------ recreate table test_ns_03( id time with time zone ,txt_short varchar(991) @@ -197,11 +81,6 @@ ,txt_short varchar(990) ); - select * from test_ns_03 order by id; -- must use refetch - - select * from test_ns_04 order by id; -- must NOT use refetch - ------------------------------------------ - recreate table test_ns_05( id varchar(1) character set utf8 collate unicode_ci_ai ,txt_short varchar(993) @@ -211,478 +90,798 @@ id varchar(1) character set utf8 collate unicode_ci_ai ,txt_short varchar(992) ); + commit; - select * from test_ns_05 order by id; -- must use refetch - - select * from test_ns_06 order by id; -- must NOT use refetch + recreate view v_unioned as + select id, txt_broad from test + union all + select -1, 'qwerty' + from rdb$database rows 0; + commit; +""" +db = db_factory(init = init_sql) + +query_map = { + ########################## p e r s i s t e n t c o l u m n s ################################## + + 1000 : ( 'select txt_short from test a01 order by id' , 'Must NOT use refetch because length of non-key column is less than threshold' ) + ,1010 : ( 'select txt_broad from test a02 order by id' , 'MUST use refetch because length of non-key column is greater than threshold' ) + ,1020 : ( 'select txt_short from test a03 order by id rows 1' , 'MUST use refetch regardless on length of column because ROWS presents' ) + + ########################## c o m p u t e d c o l u m n s ##################################### + + ,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' ) + ,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' ) + + ###################### p r e d i c a t e s [N O T] I N, A L L, A N Y ######################## + + ,3000 : ( "select id from test a04 where '' in (select txt_short from test x04 where txt_short = '' order by id)" , '*** not [yet] commented ***' ) + ,3010 : ( "select id from test a05 where '' in (select txt_broad from test x05 where txt_broad = '' order by id)" , '*** not [yet] commented ***' ) + ,3020 : ( "select id from test a06 where '' not in (select txt_short from test x06 where txt_short>'' order by id)" , '*** not [yet] commented ***' ) + ,3030 : ( "select id from test a07 where '' not in (select txt_broad from test x07 where txt_broad>'' order by id)" , '*** not [yet] commented ***' ) + ,3040 : ( "select id from test a08 where '' > all (select id from test x08 where txt_short>'' order by id)" , '*** not [yet] commented ***' ) + ,3050 : ( "select id from test a09 where '' > all (select id from test x09 where txt_broad>'' order by id)" , '*** not [yet] commented ***' ) + ,3060 : ( "select id from test a10 where '' <> any (select id from test x10 where txt_short>'' order by id)" , '*** not [yet] commented ***' ) + ,3070 : ( "select id from test a11 where '' <> any (select id from test x11 where txt_broad>'' order by id)" , '*** not [yet] commented ***' ) + + ######################################## e x i s t s ########################################### + # Predicate "EXISTS" must turn on refetching regardless of record length + # but only when "WHERE" has column which not present in "ORDER BY" + + ,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" + ) + ,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" + ) + ,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. + """ + ) + ,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" + ) + ,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" + ) + ,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" + ) + ,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" + ) + ,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" + ) + + ###################################### v i e w s ########################################### + + ,5000 : ( 'select txt_broad from v_unioned v01 order by id' , 'Must NOT use refetch because view DDL includes UNION' ) + + ################################# e x p r e s s i o n s ##################################### + + ,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) + """ + ) + ,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) + """ + ) + + ########### n o n - s y m m e t r i c a l k e y - v a l u e d a t a t y p e s ######### + + # Following data types in common case have no ability to get column value from a key: + # * International type text has a computed key + # * Different decimal float values sometimes have same keys + # * Date/time with time zones too. + # Because of this, a field of any such datatype that is specified in "order by" list, must also be involved + # in the non-key fields and sort will deal with such "concatenated" list. + # If total length of such list not exceeds InlineSortThreshold then sort will be done without refetch. + # Otherwise refetch will occur. + # See src/jrd/opt.cpp, OPT_gen_sort() and explanation from dimitr, letter 28.12.2020 16:44 + ,7000 : ( 'select * from test_ns_01 a23 order by id' , 'MUST use refetch' ) + ,7010 : ( 'select * from test_ns_02 a24 order by id' , 'Must NOT refetch' ) + ,7020 : ( 'select * from test_ns_03 order by id' , 'MUST use refetch' ) + ,7030 : ( 'select * from test_ns_04 order by id' , 'Must NOT use refetch' ) + ,7040 : ( 'select * from test_ns_05 order by id' , 'MUST use refetch' ) + ,7050 : ( 'select * from test_ns_06 order by id' , 'Must NOT use refetch' ) +} +test_script = """ + set plan on; + set explain on; """ -act = isql_act('db', test_script) +############################################################################### -fb4x_expected_out = """ +fb4x_expected_out = f""" + 1000 + {query_map[1000][0]} + {query_map[1000][1]} Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" as "A01" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" as "A01" Full Scan + 1010 + {query_map[1010][0]} + {query_map[1010][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A02" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" as "A02" Full Scan + 1020 + {query_map[1020][0]} + {query_map[1020][1]} Select Expression - -> First N Records - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A03" Full Scan + ....-> First N Records + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Table "TEST" as "A03" Full Scan + 2000 + {query_map[2000][0]} + {query_map[2000][1]} Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" Full Scan + 2010 + {query_map[2010][0]} + {query_map[2010][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" Full Scan + 3000 + {query_map[3000][0]} + {query_map[3000][1]} Select Expression - -> Filter - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X04" Full Scan + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X04" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A04" Full Scan + ....-> Filter + ........-> Table "TEST" as "A04" Full Scan + 3010 + {query_map[3010][0]} + {query_map[3010][1]} Select Expression - -> Filter - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X05" Full Scan + ....-> Filter + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Filter + ....................-> Table "TEST" as "X05" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A05" Full Scan + ....-> Filter + ........-> Table "TEST" as "A05" Full Scan + 3020 + {query_map[3020][0]} + {query_map[3020][1]} Select Expression - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X06" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X06" Full Scan Select Expression - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X06" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X06" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A06" Full Scan + ....-> Filter + ........-> Table "TEST" as "A06" Full Scan + 3030 + {query_map[3030][0]} + {query_map[3030][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X07" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X07" Full Scan Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X07" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X07" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A07" Full Scan + ....-> Filter + ........-> Table "TEST" as "A07" Full Scan + 3040 + {query_map[3040][0]} + {query_map[3040][1]} + Select Expression + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X08" Full Scan Select Expression - -> Filter - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X08" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A08" Full Scan + ....-> Filter + ........-> Table "TEST" as "A08" Full Scan + 3050 + {query_map[3050][0]} + {query_map[3050][1]} + Select Expression + ....-> Filter + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Filter + ....................-> Table "TEST" as "X09" Full Scan Select Expression - -> Filter - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X09" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A09" Full Scan + ....-> Filter + ........-> Table "TEST" as "A09" Full Scan + 3060 + {query_map[3060][0]} + {query_map[3060][1]} Select Expression - -> Filter - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X10" Full Scan + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X10" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A10" Full Scan + ....-> Filter + ........-> Table "TEST" as "A10" Full Scan + 3070 + {query_map[3070][0]} + {query_map[3070][1]} Select Expression - -> Filter - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X11" Full Scan + ....-> Filter + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Filter + ....................-> Table "TEST" as "X11" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A11" Full Scan + ....-> Filter + ........-> Table "TEST" as "A11" Full Scan + + 4000 + {query_map[4000][0]} + {query_map[4000][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X12" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A12" Full Scan + + 4010 + {query_map[4010][0]} + {query_map[4010][1]} + Select Expression + ....-> Sort (record length: 28, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X13" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A13" Full Scan + + 4020 + {query_map[4020][0]} + {query_map[4020][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 36, key length: 12) + ............-> Filter + ................-> Table "TEST" as "X14" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A14" Full Scan + + 4030 + {query_map[4030][0]} + {query_map[4030][1]} + Select Expression + ....-> Sort (record length: 36, key length: 16) + ........-> Filter + ............-> Table "TEST" as "X15" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A15" Full Scan + 4040 + {query_map[4040][0]} + {query_map[4040][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X12" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A12" Full Scan + ....-> Refetch + ........-> Sort (record length: 36, key length: 16) + ............-> Filter + ................-> Table "TEST" as "X16" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A16" Full Scan + 4050 + {query_map[4050][0]} + {query_map[4050][1]} Select Expression - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X13" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A13" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X17" Full Scan + Select Expression + ....-> Filter + ........-> Table "TEST" as "A17" Full Scan + 4060 + {query_map[4060][0]} + {query_map[4060][1]} Select Expression - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Filter - -> Table "TEST" as "X14" Full Scan + ....-> Sort (record length: 28, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X18" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A14" Full Scan + ....-> Filter + ........-> Table "TEST" as "A18" Full Scan + 4070 + {query_map[4070][0]} + {query_map[4070][1]} Select Expression - -> Sort (record length: 36, key length: 16) - -> Filter - -> Table "TEST" as "X15" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "R X" Full Scan Select Expression - -> Filter - -> Table "TEST" as "A15" Full Scan - + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "R X" Full Scan Select Expression - -> Refetch - -> Sort (record length: 36, key length: 16) - -> Filter - -> Table "TEST" as "X16" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A16" Full Scan - - Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X17" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A17" Full Scan + ....-> Recursion + ........-> Filter + ............-> Table "TEST" as "R A19" Full Scan + ........-> Filter + ............-> Table "TEST" as "R I" Full Scan + 5000 + {query_map[5000][0]} + {query_map[5000][1]} Select Expression - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X18" Full Scan - Select Expression - -> Filter - -> Table "TEST" as "A18" Full Scan + ....-> 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 + {query_map[6000][0]} + {query_map[6000][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "R X" Full Scan - Select Expression - -> 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 + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" as "A21" Full Scan + 6010 + {query_map[6010][0]} + {query_map[6010][1]} Select Expression - -> Sort (record length: 1052, key length: 8) - -> First N Records - -> Union - -> Table "TEST" as "V01 TEST" Full Scan - -> Table "RDB$DATABASE" as "V01 RDB$DATABASE" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" as "A22" Full Scan + 7000 + {query_map[7000][0]} + {query_map[7000][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A21" Full Scan + ....-> Refetch + ........-> Sort (record length: 44, key length: 24) + ............-> Table "TEST_NS_01" as "A23" Full Scan + 7010 + {query_map[7010][0]} + {query_map[7010][1]} Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" as "A22" Full Scan + ....-> Sort (record length: 1052, key length: 24) + ........-> Table "TEST_NS_02" as "A24" Full Scan + 7020 + {query_map[7020][0]} + {query_map[7020][1]} Select Expression - -> Refetch - -> Sort (record length: 44, key length: 24) - -> Table "TEST_NS_01" as "A23" Full Scan + ....-> Refetch + ........-> Sort (record length: 36, key length: 12) + ............-> Table "TEST_NS_03" Full Scan + 7030 + {query_map[7030][0]} + {query_map[7030][1]} Select Expression - -> Sort (record length: 1052, key length: 24) - -> Table "TEST_NS_02" as "A24" Full Scan + ....-> Sort (record length: 1036, key length: 12) + ........-> Table "TEST_NS_04" Full Scan + 7040 + {query_map[7040][0]} + {query_map[7040][1]} Select Expression - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Table "TEST_NS_03" Full Scan + ....-> Refetch + ........-> Sort (record length: 36, key length: 12) + ............-> Table "TEST_NS_05" Full Scan + 7050 + {query_map[7050][0]} + {query_map[7050][1]} Select Expression - -> Sort (record length: 1036, key length: 12) - -> Table "TEST_NS_04" Full Scan - - Select Expression - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Table "TEST_NS_05" Full Scan - - Select Expression - -> Sort (record length: 1036, key length: 12) - -> Table "TEST_NS_06" Full Scan - + ....-> Sort (record length: 1036, key length: 12) + ........-> Table "TEST_NS_06" Full Scan """ -fb5x_expected_out = """ - Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" as "A01" Full Scan +############################################################################### +fb5x_expected_out = f""" + 1000 + {query_map[1000][0]} + {query_map[1000][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A02" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" as "A01" Full Scan + 1010 + {query_map[1010][0]} + {query_map[1010][1]} Select Expression - -> First N Records - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A03" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" as "A02" Full Scan + 1020 + {query_map[1020][0]} + {query_map[1020][1]} Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" Full Scan + ....-> First N Records + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Table "TEST" as "A03" Full Scan + 2000 + {query_map[2000][0]} + {query_map[2000][1]} Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" Full Scan + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" Full Scan - Sub-query (invariant) - -> Filter - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X04" Full Scan + 2010 + {query_map[2010][0]} + {query_map[2010][1]} Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A04" Full Scan + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" Full Scan + 3000 + {query_map[3000][0]} + {query_map[3000][1]} 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 - - Select Expression - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X06" Full Scan - Select Expression - -> Sort (record length: 1036, key length: 8) - -> Filter - -> Table "TEST" as "X06" Full Scan - Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A06" Full Scan - - Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X07" Full Scan + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X04" Full Scan Select Expression - -> 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 + ....-> Filter (preliminary) + ........-> Table "TEST" as "A04" Full Scan + 3010 + {query_map[3010][0]} + {query_map[3010][1]} 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 - + ....-> 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 + {query_map[3020][0]} + {query_map[3020][1]} + Select Expression + ....-> Sort (record length: 1036, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X06" Full Scan + Select Expression + ....-> 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 + {query_map[3030][0]} + {query_map[3030][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X07" Full Scan + Select Expression + ....-> 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 + {query_map[3040][0]} + {query_map[3040][1]} Sub-query (invariant) - -> Filter - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X09" Full Scan + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X08" Full Scan Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A09" Full Scan + ....-> Filter (preliminary) + ........-> Table "TEST" as "A08" Full Scan + 3050 + {query_map[3050][0]} + {query_map[3050][1]} 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 - + ....-> 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 + {query_map[3060][0]} + {query_map[3060][1]} Sub-query (invariant) - -> Filter - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X11" Full Scan + ....-> Filter + ........-> Sort (record length: 1036, key length: 8) + ............-> Filter + ................-> Table "TEST" as "X10" Full Scan Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A11" Full Scan + ....-> Filter (preliminary) + ........-> Table "TEST" as "A10" Full Scan + 3070 + {query_map[3070][0]} + {query_map[3070][1]} + 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 + {query_map[4000][0]} + {query_map[4000][1]} Sub-query (invariant) - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X12" Full Scan + ....-> 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 + ....-> Filter (preliminary) + ........-> Table "TEST" as "A12" Full Scan + 4010 + {query_map[4010][0]} + {query_map[4010][1]} Sub-query (invariant) - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X13" Full Scan + ....-> Sort (record length: 28, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X13" Full Scan Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A13" Full Scan + ....-> Filter (preliminary) + ........-> Table "TEST" as "A13" Full Scan + 4020 + {query_map[4020][0]} + {query_map[4020][1]} Sub-query (invariant) - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Filter - -> Table "TEST" as "X14" Full Scan + ....-> 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 + ....-> Filter (preliminary) + ........-> Table "TEST" as "A14" Full Scan + 4030 + {query_map[4030][0]} + {query_map[4030][1]} Sub-query (invariant) - -> Sort (record length: 36, key length: 16) - -> Filter - -> Table "TEST" as "X15" Full Scan + ....-> Sort (record length: 36, key length: 16) + ........-> Filter + ............-> Table "TEST" as "X15" Full Scan Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A15" Full Scan + ....-> Filter (preliminary) + ........-> Table "TEST" as "A15" Full Scan + 4040 + {query_map[4040][0]} + {query_map[4040][1]} Sub-query (invariant) - -> Refetch - -> Sort (record length: 36, key length: 16) - -> Filter - -> Table "TEST" as "X16" Full Scan + ....-> 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 + ....-> Filter (preliminary) + ........-> Table "TEST" as "A16" Full Scan + 4050 + {query_map[4050][0]} + {query_map[4050][1]} Sub-query (invariant) - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X17" Full Scan + ....-> 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 + ....-> Filter (preliminary) + ........-> Table "TEST" as "A17" Full Scan + 4060 + {query_map[4060][0]} + {query_map[4060][1]} Sub-query (invariant) - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "X18" Full Scan + ....-> Sort (record length: 28, key length: 8) + ........-> Filter + ............-> Table "TEST" as "X18" Full Scan Select Expression - -> Filter (preliminary) - -> Table "TEST" as "A18" Full Scan + ....-> Filter (preliminary) + ........-> Table "TEST" as "A18" Full Scan + 4070 + {query_map[4070][0]} + {query_map[4070][1]} Sub-query - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Filter - -> Table "TEST" as "R X" Full Scan + ....-> 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 - - Select Expression - -> Sort (record length: 1052, key length: 8) - -> First N Records - -> Union - -> Table "TEST" as "V01 TEST" Full Scan - -> Table "RDB$DATABASE" as "V01 RDB$DATABASE" Full Scan - - Select Expression - -> Refetch - -> Sort (record length: 28, key length: 8) - -> Table "TEST" as "A21" Full Scan - - Select Expression - -> Sort (record length: 1036, key length: 8) - -> Table "TEST" as "A22" Full Scan + ....-> 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 + {query_map[5000][0]} + {query_map[5000][1]} + 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 + {query_map[6000][0]} + {query_map[6000][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 28, key length: 8) + ............-> Table "TEST" as "A21" Full Scan + + 6010 + {query_map[6010][0]} + {query_map[6010][1]} + Select Expression + ....-> Sort (record length: 1036, key length: 8) + ........-> Table "TEST" as "A22" Full Scan + + 7000 + {query_map[7000][0]} + {query_map[7000][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 44, key length: 24) + ............-> Table "TEST_NS_01" as "A23" Full Scan + + 7010 + {query_map[7010][0]} + {query_map[7010][1]} + Select Expression + ....-> Sort (record length: 1052, key length: 24) + ........-> Table "TEST_NS_02" as "A24" Full Scan + + 7020 + {query_map[7020][0]} + {query_map[7020][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 36, key length: 12) + ............-> Table "TEST_NS_03" Full Scan + + 7030 + {query_map[7030][0]} + {query_map[7030][1]} + Select Expression + ....-> Sort (record length: 1036, key length: 12) + ........-> Table "TEST_NS_04" Full Scan + + 7040 + {query_map[7040][0]} + {query_map[7040][1]} + Select Expression + ....-> Refetch + ........-> Sort (record length: 36, key length: 12) + ............-> Table "TEST_NS_05" Full Scan + + 7050 + {query_map[7050][0]} + {query_map[7050][1]} + Select Expression + ....-> Sort (record length: 1036, key length: 12) + ........-> Table "TEST_NS_06" Full Scan +""" - Select Expression - -> Refetch - -> Sort (record length: 44, key length: 24) - -> Table "TEST_NS_01" as "A23" Full Scan +act = python_act('db') - Select Expression - -> Sort (record length: 1052, key length: 24) - -> Table "TEST_NS_02" as "A24" Full Scan +#----------------------------------------------------------- - Select Expression - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Table "TEST_NS_03" Full Scan +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped - Select Expression - -> Sort (record length: 1036, key length: 12) - -> Table "TEST_NS_04" Full Scan - - Select Expression - -> Refetch - -> Sort (record length: 36, key length: 12) - -> Table "TEST_NS_05" Full Scan - - Select Expression - -> Sort (record length: 1036, key length: 12) - -> Table "TEST_NS_06" Full Scan -""" +#----------------------------------------------------------- @pytest.mark.version('>=4.0') -def test_1(act: Action): +def test_1(act: Action, capsys): + with act.db.connect() as con: + cur = con.cursor() + for q_idx, q_tuple in query_map.items(): + test_sql, qry_comment = q_tuple[:2] + ps = cur.prepare(test_sql) + print(q_idx) + print(test_sql) + print(qry_comment) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + ps.free() + act.expected_stdout = fb4x_expected_out if act.is_version('<5') else fb5x_expected_out - act.execute() + act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout - From 3aa1d699839e7e6296febf6347b7c57d69df9015 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Sep 2024 23:05:26 +0300 Subject: [PATCH 0157/1064] Added/Updated tests\bugs\gh_4314_test.py: Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. --- tests/bugs/gh_4314_test.py | 122 +++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tests/bugs/gh_4314_test.py diff --git a/tests/bugs/gh_4314_test.py b/tests/bugs/gh_4314_test.py new file mode 100644 index 00000000..581c3be1 --- /dev/null +++ b/tests/bugs/gh_4314_test.py @@ -0,0 +1,122 @@ +#coding:utf-8 + +""" +ID: issue-4314 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/4314 +TITLE: Sub-optimal predicate checking while selecting from a view [CORE3981] +DESCRIPTION: +NOTES: + [20.08.2024] pzotov + Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. +""" +import locale +import re + +import pytest +from firebird.qa import * + +init_sql = """ + recreate table rr( + rel_name varchar(63) + ,id int + ,fid int + ); + + recreate table rf( + rel_name varchar(63) + ,fid int + ,fnm varchar(63) + ); + insert into rr + select a.rdb$relation_name, a.rdb$relation_id, a.rdb$field_id + from rdb$relations a + ; + insert into rf select f.rdb$relation_name, f.rdb$field_id, f.rdb$field_name + from rdb$relation_fields f + ; + commit; + + alter table rr add constraint rr_rel_name_unq unique (rel_name); + create index rr_id on rr (id); + + alter table rf add constraint rf_fnm_rel_name_unq unique(fnm, rel_name); + create index rf_rel_name on rf(rel_name); + + recreate view v as + select r.rel_name, abs(r.id) as id + from rr r + left + join rf on r.rel_name = rf.rel_name and r.fid = rf.fid + where r.id < 128; + + set statistics index rr_rel_name_unq; + set statistics index rr_id; + set statistics index rf_fnm_rel_name_unq; + set statistics index rf_rel_name; + 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('>=3.0') +def test_1(act: Action, capsys): + + query_from_view = """ + select /* trace_tag: VIEW */ v.rel_name as v_rel_name, v.id as v_id from v + where id = 0 + """ + query_from_dt = """ + select /* trace_tag: DERIVED TABLE */ d.rel_name as d_rel_name, d.id as d_id + from ( + select r.rel_name, abs(r.id) as id + from rr r + left + join rf on r.rel_name = rf.rel_name and r.fid = rf.fid + where r.id < 128 + ) d + where d.id = 0 + """ + + with act.db.connect() as con: + cur = con.cursor() + for test_sql in (query_from_view, query_from_dt): + ps = cur.prepare(test_sql) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + expected_stdout = """ + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Filter + ................-> Table "RR" as "V R" Access By ID + ....................-> Bitmap + ........................-> Index "RR_ID" Range Scan (upper bound: 1/1) + ............-> Filter + ................-> Table "RF" as "V RF" Access By ID + ....................-> Bitmap + ........................-> Index "RF_REL_NAME" Range Scan (full match) + + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Filter + ................-> Table "RR" as "D R" Access By ID + ....................-> Bitmap + ........................-> Index "RR_ID" Range Scan (upper bound: 1/1) + ............-> Filter + ................-> Table "RF" as "D RF" Access By ID + ....................-> Bitmap + ........................-> Index "RF_REL_NAME" Range Scan (full match) + """ + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 02a8cf7ffc787bbc3490d1661e148c3a0faf7ba8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 3 Sep 2024 09:14:24 +0300 Subject: [PATCH 0158/1064] Added/Updated tests\bugs\gh_8225_test.py: Uncomment display of explained plan --- tests/bugs/gh_8225_test.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/bugs/gh_8225_test.py b/tests/bugs/gh_8225_test.py index e923eaee..47eeeab7 100644 --- a/tests/bugs/gh_8225_test.py +++ b/tests/bugs/gh_8225_test.py @@ -6,11 +6,9 @@ TITLE: Problematic queries when SubQueryConversion = true DESCRIPTION: NOTES: - [23.08.2024] pzotov - 1. Explained plan output temporary disabled: there is question about missed(?) indentation after 'Refetch'. - Sent letter to dimitr, 23.08.2024 21:42. - 2. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. - Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + [03.09.2024] pzotov + Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. Confirmed bug on 5.0.2.1479-adfe97a. Checked on 5.0.2.1482-604555f. @@ -94,15 +92,36 @@ def test_1(act: Action, capsys): print(r[0],r[1]) ps = cur.prepare(test_sql) - # temporary, until question with indentation will be solved by dimitr -- 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')]) ) for r in cur.execute(ps): print(r[0],r[1]) con.rollback() act.expected_stdout = f""" SubQueryConversion true + + Select Expression + ....-> First N Records + ........-> Filter + ............-> Hash Join (semi) + ................-> Refetch + ....................-> Sort (record length: 28, key length: 8) + ........................-> Table "DEPARTMENT" as "D" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "EMPLOYEE" as "E" Full Scan 2 d2 + SubQueryConversion false + + Sub-query + ....-> Filter + ........-> Table "EMPLOYEE" as "E" Full Scan + Select Expression + ....-> First N Records + ........-> Refetch + ............-> Sort (record length: 28, key length: 8) + ................-> Filter + ....................-> Table "DEPARTMENT" as "D" Full Scan 2 d2 """ act.stdout = capsys.readouterr().out From fbb6793e768b7df76ab9676d236185323c8d3dd3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 3 Sep 2024 21:19:09 +0300 Subject: [PATCH 0159/1064] Added/Updated tests\bugs\gh_7128_test.py: Checked on 6.0.0.447, 5.0.2.1487, 4.0.6.3142; 3.0.13.33793 raises 'firebird.driver.types.DatabaseError: Invalid resultset interface' --- tests/bugs/gh_7128_test.py | 87 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 tests/bugs/gh_7128_test.py diff --git a/tests/bugs/gh_7128_test.py b/tests/bugs/gh_7128_test.py new file mode 100644 index 00000000..a49263ad --- /dev/null +++ b/tests/bugs/gh_7128_test.py @@ -0,0 +1,87 @@ +#coding:utf-8 +""" +ID: issue-7128 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7128 +TITLE: Incorrect error message with isc_sql_interprete() +DESCRIPTION: +NOTES: + [28.03.2024] pzotov + Bug caused crash of FB up to 5.0.0.890 (10-jan-2023). + Since 5.0.0.905 (11-jan-2023) following error raises: + Invalid resultset interface + -901 + 335545049 + + [03.09.2024] pzotov + 1. Warning is issued: + $PYTHON_HOME/Lib/site-packages/firebird/driver/interfaces.py:710: FirebirdWarning: Invalid resultset interface + self._check() + It was decided to suppress warning by using 'warnings' package. + + 2. Result for snapshots with date = 09-feb-2022: + 3.0.9.33560: + Exception ignored in: + Traceback (most recent call last): + File "$PYTHON_HOME/Lib/site-packages/firebird/driver/core.py", line 3047, in __del__ + File "$PYTHON_HOME/Lib/site-packages/firebird/driver/core.py", line 3788, in close + File "$PYTHON_HOME/Lib/site-packages/firebird/driver/core.py", line 3655, in _clear + File "$PYTHON_HOME/Lib/site-packages/firebird/driver/interfaces.py", line 709, in close + OSError: exception: access violation writing 0x0000000000000024 + 4.0.1.2175: passed. + 5.0.0.393: crashed, + > raise self.__report(DatabaseError, self.status.get_errors()) + E firebird.driver.types.DatabaseError: Error writing data to the connection. + E -send_packet/send + 3. Version 3.0.13.33793 raises: + > raise self.__report(DatabaseError, self.status.get_errors()) + E firebird.driver.types.DatabaseError: Invalid resultset interface + (and this exceprion is not catched for some reason). + + Checked on 6.0.0.447, 5.0.2.1487, 4.0.6.3142 +""" + +import pytest +from firebird.qa import * +from firebird.driver import tpb, Isolation, TraLockResolution, TraAccessMode, DatabaseError, FirebirdWarning +import time +import warnings + +db = db_factory() +act = python_act('db') + +@pytest.mark.version('>=4.0') +def test_1(act: Action, capsys): + + tpb_isol_set = (Isolation.SERIALIZABLE, Isolation.SNAPSHOT, Isolation.READ_COMMITTED_READ_CONSISTENCY, Isolation.READ_COMMITTED_RECORD_VERSION, Isolation.READ_COMMITTED_NO_RECORD_VERSION) + + with act.db.connect() as con: + for x_isol in tpb_isol_set: + custom_tpb = tpb(isolation = x_isol, lock_timeout = 0) + tx = con.transaction_manager(custom_tpb) + cur = tx.cursor() + tx.begin() + with warnings.catch_warnings(): + warnings.filterwarnings('ignore') + try: + print(x_isol.name) + cur.execute('select 0 from rdb$types rows 2') + cur.fetchone() + tx._cursors = [] + tx.commit() + cur.fetchone() + except DatabaseError as e: + print(e.__str__()) + print(e.sqlcode) + for g in e.gds_codes: + print(g) + finally: + cur.close() + + act.expected_stdout = f""" + {x_isol.name} + Invalid resultset interface + -901 + 335545049 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From e8ccc02275f615f6a3e4e0d6fba84b930975a573 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 11:59:41 +0300 Subject: [PATCH 0160/1064] Added/Updated tests\bugs\core_4301_test.py: Added 'using plugin Srp' into 'CREATE USER' statements, in order to check 'COMMENT ON USER' with non-ascii text. --- tests/bugs/core_4301_test.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4301_test.py b/tests/bugs/core_4301_test.py index da3c1d07..fb5c45a7 100644 --- a/tests/bugs/core_4301_test.py +++ b/tests/bugs/core_4301_test.py @@ -7,6 +7,9 @@ DESCRIPTION: JIRA: CORE-4301 FBTEST: bugs.core_4301 +NOTES: + [04.09.2024] pzotov + Added 'using plugin Srp' into 'CREATE USER' statements, in order to check 'COMMENT ON USER' with non-ascii text. """ import pytest @@ -20,29 +23,43 @@ user_b = user_factory('db', name='u30b', password='u30b', do_not_create=True) test_script = """ - -- Note: this test differs from ticket: instead of add COMMENTS to users - -- it only defines their `firstname` attribute, because sec$users.sec$description - -- can be displayed only when plugin UserManager = Srp. -- Field `firstname` is defined as: -- VARCHAR(32) CHARACTER SET UNICODE_FSS COLLATE UNICODE_FSS -- we can put in it max 16 non-ascii characters - create or alter user u30a password 'u30a' firstname 'Полиграф Шариков'; - create or alter user u30b password 'u30b' firstname 'Léopold Frédéric'; + create or alter user u30a password 'u30a' firstname 'Полиграф Шариков' using plugin Srp; + create or alter user u30b password 'u30b' firstname 'Léopold Frédéric' using plugin Srp; commit; + comment on user u30a is 'это кто-то из наших'; + comment on user u30b is 'é alguém do Brasil'; + commit; + /* + show domain rdb$user; + show domain SEC$NAME_PART; + show table sec$users; + */ set list on; - select u.sec$user_name, u.sec$first_name + select + -- 3.x: CHAR(31) CHARACTER SET UNICODE_FSS Nullable + -- 4.x, 5.x: (RDB$USER) CHAR(63) Nullable + -- FB 6.x: (RDB$USER) CHAR(63) CHARACTER SET UTF8 Nullable + u.sec$user_name + ,u.sec$first_name -- (SEC$NAME_PART) VARCHAR(32) Nullable + ,u.sec$description as descr_blob_id -- (RDB$DESCRIPTION) BLOB segment 80, subtype TEXT Nullable from sec$users u where upper(u.sec$user_name) in (upper('u30a'), upper('u30b')); commit; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [ ('DESCR_BLOB_ID.*',''),('[ \t]+',' ') ] ) expected_stdout = """ SEC$USER_NAME U30A SEC$FIRST_NAME Полиграф Шариков + это кто-то из наших + SEC$USER_NAME U30B SEC$FIRST_NAME Léopold Frédéric + é alguém do Brasil """ @pytest.mark.version('>=3.0') From 21b75e0a2609101ccd03eff141e303c46cddb0e2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 12:30:37 +0300 Subject: [PATCH 0161/1064] Added/Updated tests\bugs\gh_0731_test.py: Checked on all recent 3.x ... 6.x --- tests/bugs/gh_0731_test.py | 97 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/bugs/gh_0731_test.py diff --git a/tests/bugs/gh_0731_test.py b/tests/bugs/gh_0731_test.py new file mode 100644 index 00000000..4b81db95 --- /dev/null +++ b/tests/bugs/gh_0731_test.py @@ -0,0 +1,97 @@ +#coding:utf-8 + +""" +ID: issue-731 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/731 +TITLE: coalesce fails with data type varchar and a non ascii value [CORE388] +DESCRIPTION: +NOTES: + [04.09.2024] pzotov + The issue seems to be fixed long ago. + Old FB versions can not be checked on current firebird QA. + Checked on all recent 3.x ... 6.x -- all fine. +""" + +import pytest +from firebird.qa import * + +init_sql = """ + recreate table trans_table + ( + tcode smallint + not null, + code smallint + not null, + name varchar(10), + constraint trans_table_primarykey primary key + (tcode, code) + ); + + recreate table class1 + ( + class_name varchar(10) + not null, + class_num smallint + not null, + teacher_id integer, + constraint pk_class1 primary key (class_name, class_num) + ); + + recreate table class2 + ( + class_name varchar(10) + not null, + class_num smallint + not null, + teacher_id integer, + constraint pk_class2 primary key (class_name, class_num) + ); + + set term ^; + create trigger class1_bi for class1 active before insert position 0 as + declare name varchar(10); + begin + select name from trans_table c where c.tcode=2 and c.code=new.class_name + into :name; + new.class_name = case when :name is null then new.class_name else :name end; + -- new.class_name = coalesce(:name, new.class_name); + end + ^ + + create trigger class2_bi for class2 active before insert position 0 as + declare name varchar(10); + begin + select name from trans_table c where c.tcode=2 and c.code=new.class_name + into :name; + -- new.class_name = case when :name is null then new.class_name else :name end; + new.class_name = coalesce(:name, new.class_name); + end + ^ + set term ;^ + commit; +""" +db = db_factory(init = init_sql, charset='win1252') + +test_script = """ + set bail on; + set list on; + insert into trans_table(tcode, code, name) values (2, 1, 'à'); + -- passed + insert into class1(class_name, class_num, teacher_id) values (1, 1, null); + -- failed + insert into class2(class_name, class_num, teacher_id) values (1, 1, null); + select 'Passed' as msg from rdb$database; +""" + +act = isql_act('db', test_script, substitutions = [ ('[ \t]+',' ') ]) + +expected_stdout = """ + MSG Passed +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(charset = 'win1252') + assert act.clean_stdout == act.clean_expected_stdout + From 75230e41813be6ea5122324fbdd97110d74cec93 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 12:43:07 +0300 Subject: [PATCH 0162/1064] Added/Updated tests\bugs\core_0986_test.py: minor changes: removed not working comments --- tests/bugs/core_0986_test.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_0986_test.py b/tests/bugs/core_0986_test.py index 0402b37d..77ed12ce 100644 --- a/tests/bugs/core_0986_test.py +++ b/tests/bugs/core_0986_test.py @@ -23,18 +23,18 @@ expected_stdout_a = """create collation "Циферки" for utf8 from unicode case insensitive 'NUMERIC-SORT=1';""" expected_stderr_a_40 = """ -Statement failed, SQLSTATE = 22018 -arithmetic exception, numeric overflow, or string truncation --Cannot transliterate character between character sets -After line 4 in file non_ascii_ddl.sql + Statement failed, SQLSTATE = 22018 + arithmetic exception, numeric overflow, or string truncation + -Cannot transliterate character between character sets + After line 4 in file non_ascii_ddl.sql """ expected_stderr_a_30 = """ -Statement failed, SQLSTATE = 22000 -unsuccessful metadata update --CREATE COLLATION Циферки failed --Malformed string -After line 4 in file non_ascii_ddl.sql + Statement failed, SQLSTATE = 22000 + unsuccessful metadata update + -CREATE COLLATION Циферки failed + -Malformed string + After line 4 in file non_ascii_ddl.sql """ non_ascii_ddl=''' @@ -171,8 +171,6 @@ '; -------------------------------------------------- commit; - --/* - --TEMPLY COMMENTED UNTIL CORE-5221 IS OPEN: set echo on; show collation; show domain; @@ -183,25 +181,28 @@ show view; show procedure; show role; - --*/ set list on; set echo off; select 'Metadata created OK.' as msg from rdb$database; ''' -tmp_file = temp_file('non_ascii_ddl.sql') +tmp_file = temp_file('tmp_0986_non_ascii_ddl.sql') @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_file: Path): tmp_file.write_bytes(non_ascii_ddl.encode('cp1251')) + # run without specifying charset + ################################ act.expected_stdout = expected_stdout_a act.expected_stderr = expected_stderr_a_40 if act.is_version('>=4.0') else expected_stderr_a_30 act.isql(switches=['-q'], input_file=tmp_file, charset=None, io_enc='cp1251') assert (act.clean_stdout == act.clean_expected_stdout and act.clean_stderr == act.clean_expected_stderr) - # run with charset + + # run _with_ charset + #################### act.reset() act.isql(switches=['-q'], input_file=tmp_file, charset='win1251', io_enc='cp1251') assert act.clean_stdout.endswith('Metadata created OK.') From f61d3d5a9b1a56e4f0a006be6dbc0ebf3e5c1203 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 15:21:25 +0300 Subject: [PATCH 0163/1064] Added/Updated tests\bugs\gh_8241_test.py: Checked on 6.0.0.450-8591572, 5.0.2.1493-eb720e8. --- tests/bugs/gh_8241_test.py | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/bugs/gh_8241_test.py diff --git a/tests/bugs/gh_8241_test.py b/tests/bugs/gh_8241_test.py new file mode 100644 index 00000000..4d54cdcb --- /dev/null +++ b/tests/bugs/gh_8241_test.py @@ -0,0 +1,54 @@ +#coding:utf-8 +""" +ID: issue-8241 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8241 +TITLE: gbak may lose NULLs in restore +DESCRIPTION: +NOTES: + Restore must use gbak utility, target DB must be prefixed by 'localhost:'. + + Confirmed bug on 6.0.0.447, 5.0.2.1487 + Checked on 6.0.0.450-8591572, 5.0.2.1493-eb720e8. +""" + +import pytest +from firebird.qa import * +from pathlib import Path +import time + +init_sql = """ + create table t ("TABLE" integer); + insert into t values (null); + insert into t values (null); + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db') + +tmp_fbk = temp_file('tmp_8241.fbk') +tmp_res = temp_file('tmp_8241.fdb') + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action, tmp_fbk: Path, tmp_res: Path, capsys): + + with act.connect_server() as srv: + srv.database.set_sql_dialect(database=act.db.db_path, dialect=1) + + act.gbak(switches=['-b', act.db.db_path, str(tmp_fbk)]) + act.gbak(switches=['-rep', str(tmp_fbk), f'localhost:{act.db.db_path}']) + + # NOTE! THIS PREVENTS FROM REPRODUCING BUG: + # DO NOT USE >>> act.gbak(switches=['-se', 'localhost:service_mgr', '-rep', str(tmp_fbk), act.db.db_path]) + + with act.db.connect() as con: + cur = con.cursor() + cur.execute('select "TABLE" from t') + for r in cur: + print(r[0]) + + act.expected_stdout = f""" + None + None + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 39e0c356d18ebcc85aa72f258604add35b77fcce Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 16:45:16 +0300 Subject: [PATCH 0164/1064] Added/Updated tests\bugs\core_0986_test.py: minor changes --- tests/bugs/core_0986_test.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_0986_test.py b/tests/bugs/core_0986_test.py index 77ed12ce..f13595fd 100644 --- a/tests/bugs/core_0986_test.py +++ b/tests/bugs/core_0986_test.py @@ -2,7 +2,7 @@ """ ID: issue-1393 -ISSUE: 1393 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1393 TITLE: Non-ASCII quoted identifiers are not converted to metadata (UNICODE_FSS) charset DESCRIPTION: JIRA: CORE-986 @@ -62,8 +62,7 @@ create role "манагер"; create role "начсклд"; - -- TEMPLY COMMENTED UNTIL CORE-5209 IS OPEN: - -- ISQL -X ignores connection charset for text of EXCEPTION message (restoring it in initial charset when exception was created) + -- enabled since CORE-5209 was fixed: recreate exception "Невзлет" 'Запись обломалась, ваши не пляшут. Но не стесняйтесь и обязательно заходите еще, мы всегда рады видеть вас. До скорой встречи, товарищ!'; commit; @@ -206,5 +205,3 @@ def test_1(act: Action, tmp_file: Path): act.reset() act.isql(switches=['-q'], input_file=tmp_file, charset='win1251', io_enc='cp1251') assert act.clean_stdout.endswith('Metadata created OK.') - - From b70f0174883d9c5593905ecfab1c9feb20f58bc7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 20:04:56 +0300 Subject: [PATCH 0165/1064] Add marker 'intl' for tests which deal with non-ascii characters --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index 90668c59..9da79511 100644 --- a/pytest.ini +++ b/pytest.ini @@ -3,6 +3,7 @@ console_output_style = count # testpaths = tests # addopts = --server local --install-terminal markers = + intl: mark a test as dealing with non-ascii characters scroll_cur: mark a test as dealing with scrollable cursor es_eds: mark a test as dealing with ES/EDS mechanism trace: mark a test as dealing with trace From fb31b6c73926949948fabd6b514ed917499ddf77 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 4 Sep 2024 20:06:13 +0300 Subject: [PATCH 0166/1064] Added/Updated tests\functional\intl\test_non_ascii_firebird_and_trace_utf8.py: Checked 6.0.0.450, 5.0.2.1493, 4.0.6.3142 (on Windows). --- .../test_non_ascii_firebird_and_trace_utf8.py | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py diff --git a/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py b/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py new file mode 100644 index 00000000..42f46800 --- /dev/null +++ b/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py @@ -0,0 +1,178 @@ +#coding:utf-8 + +""" +ID: functional.intl.test_non_ascii_firebird_and_trace_utf8.py +TITLE: Check ability to obtain non-ascii content from firebird.log and trace when use ON DISCONNECT trigger and exception with non-ascii names, charset = UTF8. +DESCRIPTION: + We can make engine to put something in firebird.log by creating ON DISCONNECT trigger which raises exception. + (see https://github.com/FirebirdSQL/firebird/issues/4282). + In order this trigger not fired when we just create DB, aux user ('TMP_WORKER') is created and trigger will fire only for him. + Before making connection as user 'TMP_WORKER', we: + * get content of firebird.log + * launch trace + After tmp_worker completes its work (running ISQL with single command: 'quit'), we get again content of + firebird.log and trace for further parsing. + + Finally, we check that: + * trace contains messages about raised exception (with message) and failed trigger (with call stack); + * difference in firebird.log contains messages similar to trace +NOTES: + [04.09.2024] pzotov + Test makes connections to DB using charset = 'utf8' and uses io_enc = 'utf-8' when obtaining content of firebird.log and trace. + Checked 6.0.0.450, 5.0.2.1493, 4.0.6.3142 (on Windows). +""" + +import pytest +from firebird.qa import * +import re +import locale +from pathlib import Path +from difflib import unified_diff +import time + +tmp_worker = user_factory('db', name='tmp_worker', password='123') +#tmp_sql = temp_file('tmp_non_ascii.sql') + +db = db_factory(charset = 'utf8') +substitutions = [ ('.* FAILED EXECUTE_TRIGGER_FINISH', 'FAILED EXECUTE_TRIGGER_FINISH'), + ('.* ERROR AT purge_attachment', 'ERROR AT purge_attachment'), + ('(,)?\\s+line(:)?\\s+\\d+(,)?\\s+col(:)?\\s+\\d+', '') + ] + +act = python_act('db', substitutions = substitutions) + +@pytest.mark.trace +@pytest.mark.version('>=4.0') +def test_1(act: Action, tmp_worker: User, capsys): + + init_sql = f""" + set list on; + set bail on; + create exception "paramètre non trouvé" q'#Paramètre "@1" a une valeur incorrecte ou n'a pas été trouvé dans#'; + set term ^; + ^ + create trigger "gâchette de déconnexion" on disconnect as + begin + if ( current_user != '{act.db.user}' ) then + begin + exception "paramètre non trouvé" using ('fréquence fermée'); + end + end + ^ + set term ;^ + commit; + """ + + #tmp_sql.write_bytes( bytes(init_sql.encode('utf-8')) ) + #act.isql(switches=['-q'], input_file = tmp_sql, combine_output = True, charset = 'utf8', io_enc = 'utf-8') + + act.expected_stdout = '' + act.isql(switches=['-q'], input = init_sql, combine_output = True, charset = 'utf8', io_enc = 'utf-8') + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # ---------------------------------------------------------------------------------------------- + with act.connect_server(encoding = 'utf-8') as srv: + srv.info.get_log() + fb_log_init = srv.readlines() + # ---------------------------------------------------------------------------------------------- + + trace_cfg_items = [ + 'log_connections = true', + 'log_transactions = true', + 'time_threshold = 0', + 'log_errors = true', + 'log_statement_finish = true', + 'log_trigger_finish = true', + 'max_sql_length = 32768', + ] + + with act.trace(db_events = trace_cfg_items, encoding='utf-8'): + test_sql = f""" + set names utf8; + connect '{act.db.dsn}' user {tmp_worker.name} password '{tmp_worker.password}'; + quit; + """ + act.isql(switches = ['-q'], input = test_sql, connect_db=False, credentials = False, combine_output = True, io_enc = 'utf-8') + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # ---------------------------------------------------------------------------------------------- + + allowed_patterns = \ + ( + re.escape(') FAILED EXECUTE_TRIGGER_FINISH') + ,re.escape(') ERROR AT purge_attachment') + ,re.escape('335544382 :') # name of exception: paramètre non trouvé (without quotes) + ,re.escape('335545016 :') # message of exception: Paramètre "fréquence fermée" a une valeur incorrecte ou n'a pas été trouvé dans + ,re.escape('335544842 : At trigger') + ) + allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in allowed_patterns ] + + # Example of trace: + # 2024-09-04T18:57:20.7950 (2184:00000000016B23C0) ERROR AT purge_attachment + # ... + # 335544517 : exception 1 + # 335544382 : paramètre non trouvé + # 335545016 : Paramètre "fréquence fermée" a une valeur incorrecte ou n'a pas été trouvé dans + # 335544842 : At trigger 'gâchette de déconnexion' line: 5, col: 17 + + for line in act.trace_log: + #print(line) + if line.strip(): + if act.match_any(line.strip(), allowed_patterns): + print(line.strip()) + + expected_trace_log = """ + FAILED EXECUTE_TRIGGER_FINISH + ERROR AT purge_attachment + 335544382 : paramètre non trouvé + 335545016 : Paramètre "fréquence fermée" a une valeur incorrecte ou n'a pas été trouvé dans + 335544842 : At trigger 'gâchette de déconnexion' + """ + act.expected_stdout = expected_trace_log + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + # ---------------------------------------------------------------------------------------------- + + with act.connect_server(encoding = 'utf-8') as srv: + srv.info.get_log() + fb_log_curr = srv.readlines() + srv.wait() + + # Example of firebird.log: + # + # Error at disconnect: + # exception 1 + # paramètre non trouvé + # Paramètre "fréquence fermée" a une valeur incorrecte ou n'a pas été trouvé dans + # At trigger 'gâchette de déconnexion' + + fb_log_diff_patterns = \ + ( + 'Error at disconnect' + ,'exception' + ,'paramètre non trouvé' + ,'Paramètre "fréquence fermée"' + ,'At trigger' + ) + fb_log_diff_patterns = [ re.compile(p, re.IGNORECASE) for p in fb_log_diff_patterns ] + + for line in unified_diff(fb_log_init, fb_log_curr): + if line.startswith('+'): + if act.match_any(line[1:].strip(), fb_log_diff_patterns): + print(line[1:].strip()) + + expected_log_diff = """ + Error at disconnect: + exception 1 + paramètre non trouvé + Paramètre "fréquence fermée" a une valeur incorrecte ou n'a pas été trouvé dans + At trigger 'gâchette de déconnexion' + """ + + act.expected_stdout = expected_log_diff + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 17d8f371044b31eaeadd3238b871b29b753e1768 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Sep 2024 10:07:37 +0300 Subject: [PATCH 0167/1064] Added/Updated tests\bugs\gh_0731_test.py: ISQL must work with charset = utf8. Otherwise 'Expected end of statement, encountered EOF' will raise on Linux. --- tests/bugs/gh_0731_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_0731_test.py b/tests/bugs/gh_0731_test.py index 4b81db95..6fdb0a94 100644 --- a/tests/bugs/gh_0731_test.py +++ b/tests/bugs/gh_0731_test.py @@ -9,6 +9,8 @@ [04.09.2024] pzotov The issue seems to be fixed long ago. Old FB versions can not be checked on current firebird QA. + ISQL must work with charset = utf8. Otherwise 'Expected end of statement, encountered EOF' will raise on Linux. + Checked on all recent 3.x ... 6.x -- all fine. """ @@ -92,6 +94,6 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute(charset = 'win1252') + act.execute(charset = 'utf8') assert act.clean_stdout == act.clean_expected_stdout From 1a3a9e0db701d3e8b765ba19c90493f60a48dbdb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Sep 2024 12:28:07 +0300 Subject: [PATCH 0168/1064] Added/Updated tests\bugs\gh_8219_test.py: Confirmed problem on snapshotrs before 20-aug-2024 -- see notes. Test can be used only for ServerMode = Super or SuperClassic --- tests/bugs/gh_8219_test.py | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/bugs/gh_8219_test.py diff --git a/tests/bugs/gh_8219_test.py b/tests/bugs/gh_8219_test.py new file mode 100644 index 00000000..0e248de0 --- /dev/null +++ b/tests/bugs/gh_8219_test.py @@ -0,0 +1,145 @@ +#coding:utf-8 + +""" +ID: issue-8219 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8219 +TITLE: Database creation in 3.0.12, 4.0.5 and 5.0.1 slower than in previous releases +DESCRIPTION: + We can estimate perfomance by comparison of time that is spent to create DB vs result of some crypt function. + Function crypt_hash( using SHA512) has been selected for that because of notable CPU consumation. + Stored procedured SP_GEN_HASH is created for evaluation of crypt hash, it will run loop for N_HASH_EVALUATE_COUNT times. + Duration for each measure is difference between psutil.Process(fb_pid).cpu_times() counters. + We do times call of SP and create_database(), with adding results to map. + Finally, we get ratio between medians of these measures (see 'median_ratio') + + Test is considered as passed if median_ratio less than threshold . +NOTES: + [05.09.2024] pzotov. + 1. Confirmed problem on snapshotrs before 20-aug-2024. + Medians ratio on Windows: + 1. Before fix: + 6.0.0.423: 0.39; 6.0.0.436: 0.39; 6.0.0.437: 0.35; + 5.0.1.1464: 0.42; 5.0.1.1469: 0.39; 5.0.1.1479: 0.35 + 4.0.5.3136: 0.42; 4.0.6.3142: 0.39 + 2. After fix ratio reduced to ~0.25: + 6.0.0.438: 0.21; 6.0.0.442: 0.21; 6.0.0.438: 0.21; 6.0.0.442: 0.21; 6.0.0.450: 0.24 + 5.0.2.1481: 0.25; 5.0.2.1482: 0.21; 5.0.2.1493: 0.22 + 4.0.6.3144: 0.25; 4.0.6.3149: 0.29 + + Medians ratio on Windows: + 1. Before fix: + 6.0.0.397-c734c96: 0.48; 6.0.0.438-088b529: 0.49 + 2. After fix ratio reduced to ~0.25: + 6.0.0.441-75042b5: 0.23 + 5.0.2.1481-fc71044: 0.24 + 4.0.6.3144-5a3b718: 0.27 + 2. Test DB must NOT have charset = utf8, otherwise 'implementation limit exceeded' will raise; win1251 was selected for work. + 3. Test can be used only for ServerMode = Super or SuperClassic + (because in CS a new process is made and we have no value of cpu_times() *before* DB creation). +""" +import os +import psutil +import pytest +from firebird.qa import * +from firebird.driver import driver_config, create_database, NetProtocol +from pathlib import Path + +#-------------------------------------------------------------------- +def median(lst): + n = len(lst) + s = sorted(lst) + return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None +#-------------------------------------------------------------------- + +########################### +### S E T T I N G S ### +########################### + +# How many times we create databases +N_MEASURES = 31 + +# How many iterations must be done for hash evaluation: +N_HASH_EVALUATE_COUNT = 3000 + +# Maximal value for ratio between maximal and minimal medians +# +############################################# +MAX_RATIO = 0.30 if os.name == 'nt' else 0.33 +############################################# + +init_script = \ +f''' + set term ^; + create or alter procedure sp_gen_hash (n_cnt int) as + declare v_hash varbinary(64); + declare s varchar(32765); + begin + s = lpad('', 32765, uuid_to_char(gen_uuid())); + while (n_cnt > 0) do + begin + v_hash = crypt_hash(s using SHA512); + n_cnt = n_cnt - 1; + end + end + ^ + commit + ^ +''' + +db = db_factory(init = init_script, charset = 'win1251') +act = python_act('db') +tmp_fdb = temp_file('tmp_gh_8219.tmp') + +expected_stdout = """ + Medians ratio: acceptable +""" + +@pytest.mark.version('>=4.0.5') +def test_1(act: Action, tmp_fdb: Path, capsys): + + if act.vars['server-arch'].lower() == 'classic': + pytest.skip('Can be used only for SS / SC.') + + srv_cfg = driver_config.register_server(name = 'test_srv_gh_8219', config = '') + + db_cfg_name = 'tmp_8219' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.protocol.value = NetProtocol.INET + db_cfg_object.database.value = str(tmp_fdb) + + with act.db.connect() as con: + cur=con.cursor() + cur.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur.fetchone()[0]) + + times_map = {} + for i in range(0, N_MEASURES): + fb_info_init = psutil.Process(fb_pid).cpu_times() + cur.callproc( 'sp_gen_hash', (N_HASH_EVALUATE_COUNT,) ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + times_map[ 'hash_eval', i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + fb_info_init = psutil.Process(fb_pid).cpu_times() + with create_database(db_cfg_name, user = act.db.user, password = act.db.password, overwrite = True) as dbc: + pass + fb_info_curr = psutil.Process(fb_pid).cpu_times() + times_map[ 'db_create', i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + + sp_gen_hash_median = median([v for k,v in times_map.items() if k[0] == 'hash_eval']) + sp_db_create_median = median([v for k,v in times_map.items() if k[0] == 'db_create']) + + median_ratio = sp_db_create_median / sp_gen_hash_median + + print( 'Medians ratio: ' + ('acceptable' if median_ratio <= MAX_RATIO else '/* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:9g}'.format(median_ratio), '{:9g}'.format(MAX_RATIO) ) ) ) + if median_ratio > MAX_RATIO: + print(f'CPU times for each of {N_MEASURES} measures:') + for sp_name in ('hash_eval', 'db_create', ): + print(f'{sp_name=}:') + for p in [v for k,v in times_map.items() if k[0] == sp_name]: + print(p) + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 9afb73b053d7d11eeaf5e33c7cd8fc86f31af88c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 12 Sep 2024 11:57:26 +0300 Subject: [PATCH 0169/1064] Added/Updated tests\bugs\core_2051_test.py: Removed execution plan from expected output. Requested by dimitr. --- tests/bugs/core_2051_test.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2051_test.py b/tests/bugs/core_2051_test.py index 50321f39..9a4bfcf1 100644 --- a/tests/bugs/core_2051_test.py +++ b/tests/bugs/core_2051_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-2051 FBTEST: bugs.core_2051 +NOTES: + [12.09.2024] pzotov + Removed execution plan from expected output. + Requested by dimitr, letters with subj 'core_2051_test', since 11.09.2024 17:16. """ import pytest @@ -28,16 +32,13 @@ insert into test2 values(2); commit; - set plan on; set list on; select coalesce((select t2.id from test2 t2 where t2.id = t1.id), 0) id2 from test1 t1 order by t1.id; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [ ('[ \t]+',' ') ]) expected_stdout = """ - PLAN (T2 INDEX (TEST2_PK)) - PLAN (T1 ORDER TEST1_PK) ID2 1 ID2 2 ID2 0 @@ -46,6 +47,6 @@ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1e08690886b6f814a3894af1c6da2ac5bb570b49 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 12 Sep 2024 12:31:24 +0300 Subject: [PATCH 0170/1064] Added/Updated tests\bugs\core_5118_test.py: Replaced test query so that it does not use index navigation ('plan order') but still checks indexed access. Requested by dimitr, letters with subj 'core_5118_test', since 11.09.2024 17:26. Checked on 6.0.0.452, 5.0.2.1493, 4.0.5.3136, 3.0.13.33789 --- tests/bugs/core_5118_test.py | 55 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_5118_test.py b/tests/bugs/core_5118_test.py index baff0af6..d23cd9de 100644 --- a/tests/bugs/core_5118_test.py +++ b/tests/bugs/core_5118_test.py @@ -7,6 +7,17 @@ DESCRIPTION: JIRA: CORE-5118 FBTEST: bugs.core_5118 +NOTES: + [12.09.2024] pzotov + Replaced test query so that it does not use index navigation ('plan order') but still checks indexed access. + Three separate queries with 'PLAN ... INDEX' are used instead of one with 'where IN '. + This is because of optimizer changed in 5.x and issues plan with only *one* occurrence of 'INDEX' for such cases. + See: https://github.com/FirebirdSQL/firebird/pull/7707 - "Better processing and optimization if IN ". + Commit: https://github.com/FirebirdSQL/firebird/commit/0493422c9f729e27be0112ab60f77e753fabcb5b, 04-sep-2023. + + Requested by dimitr, letters with subj 'core_5118_test', since 11.09.2024 17:26. + + Checked on 6.0.0.452, 5.0.2.1493, 4.0.5.3136, 3.0.13.33789 """ import pytest @@ -32,40 +43,40 @@ commit; """ -db = db_factory(init=init_script) +db = db_factory(init = init_script) -act = python_act('db') +act = python_act('db', substitutions = [ ('[ \t]+',' ') ]) expected_stdout = """ - PLAN (TEST ORDER TEST_CONCAT_TEXT) + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom1 prenom1 + Records affected: 1 - ID 1 - X nom1 - Y prenom1 - CONCAT_TEXT nom1 prenom1 + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom2 prenom2 + Records affected: 1 - ID 2 - X nom2 - Y prenom2 - CONCAT_TEXT nom2 prenom2 - - ID 3 - X nom3 - Y prenom3 - CONCAT_TEXT nom3 prenom3 + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom3 prenom3 + Records affected: 1 +""" - Records affected: 3 +test_sql = """ + set list on; + set plan on; + set count on; + select concat_text from test where concat_text = 'nom1 prenom1'; + select concat_text from test where concat_text = 'nom2 prenom2'; + select concat_text from test where concat_text = 'nom3 prenom3'; """ @pytest.mark.version('>=3.0') def test_1(act: Action): with act.connect_server() as srv: backup = BytesIO() - srv.database.local_backup(database=act.db.db_path, backup_stream=backup) + srv.database.local_backup(database = act.db.db_path, backup_stream = backup) backup.seek(0) - srv.database.local_restore(database=act.db.db_path, backup_stream=backup, - flags=SrvRestoreFlag.REPLACE) + srv.database.local_restore(database = act.db.db_path, backup_stream=backup, flags = SrvRestoreFlag.REPLACE) act.expected_stdout = expected_stdout - act.isql(switches=['-q'], - input='set list on; set plan on; set count on; select * from test order by concat_text;') + act.isql(switches=['-q'], input = test_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 92e0fd027b7bff38de17f5d21453f010e2f2bd7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 12 Sep 2024 21:04:46 +0300 Subject: [PATCH 0171/1064] Added/Updated tests\bugs\core_5118_test.py: dummy change in order to force subsequent QA run for all FB versions. --- tests/bugs/core_5118_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_5118_test.py b/tests/bugs/core_5118_test.py index d23cd9de..9931b9cd 100644 --- a/tests/bugs/core_5118_test.py +++ b/tests/bugs/core_5118_test.py @@ -17,7 +17,7 @@ Requested by dimitr, letters with subj 'core_5118_test', since 11.09.2024 17:26. - Checked on 6.0.0.452, 5.0.2.1493, 4.0.5.3136, 3.0.13.33789 + Checked on 6.0.0.452, 5.0.2.1493, 4.0.5.3136, 3.0.13.33789. """ import pytest From 140ba94f6c1104175880b06877c67cf0a3d2db56 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Sep 2024 22:09:28 +0300 Subject: [PATCH 0172/1064] Added/Updated tests\functional\tabloid\test_883200d1.py: Checked on 6.0.0.457 - all OK. --- tests/functional/tabloid/test_883200d1.py | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/functional/tabloid/test_883200d1.py diff --git a/tests/functional/tabloid/test_883200d1.py b/tests/functional/tabloid/test_883200d1.py new file mode 100644 index 00000000..8d6c01a0 --- /dev/null +++ b/tests/functional/tabloid/test_883200d1.py @@ -0,0 +1,58 @@ +#coding:utf-8 + +""" +ID: None +ISSUE: https://github.com/FirebirdSQL/firebird/commit/883200d1927f74baadc7eb14293d1a9fb4e517ce +TITLE: Do not re-prepare statements when execute DDL in ISQL +DESCRIPTION: +NOTES: + Confirmed duplicated PREPARE_STATEMENT in 6.0.0.454 + Checked on 6.0.0.457 - all OK. +""" + +import re +import time + +import pytest +from firebird.qa import * + +db = db_factory() + +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ +""" + +@pytest.mark.trace +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + trace_cfg_items = [ + 'time_threshold = 0', + 'log_statement_prepare = true', + 'log_initfini = false', + 'log_errors = true', + ] + + DDL_STTM = 'recreate table test(id int)' + with act.trace(db_events = trace_cfg_items, encoding='utf-8'): + act.isql(switches = ['-q'], input = DDL_STTM + ';', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + allowed_patterns = ( re.escape(DDL_STTM),) + allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in allowed_patterns ] + + for line in act.trace_log: + if line.strip(): + if act.match_any(line.strip(), allowed_patterns): + print(line.strip()) + + + expected_trace_log = f""" + {DDL_STTM} + """ + act.expected_stdout = expected_trace_log + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From b604f005ea2ddbb7bc1158bd1083371327c38e8c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 14 Sep 2024 13:46:05 +0300 Subject: [PATCH 0173/1064] Added/Updated tests\bugs\gh_8252_test.py: Checked on 5.0.2.1499-5fa4ae6. --- tests/bugs/gh_8252_test.py | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/bugs/gh_8252_test.py diff --git a/tests/bugs/gh_8252_test.py b/tests/bugs/gh_8252_test.py new file mode 100644 index 00000000..9f939e1f --- /dev/null +++ b/tests/bugs/gh_8252_test.py @@ -0,0 +1,91 @@ +#coding:utf-8 + +""" +ID: issue-8252 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8252 +TITLE: Incorrect subquery unnesting with complex dependencies (SubQueryConversion = true) +DESCRIPTION: +NOTES: + [14.09.2024] pzotov + 1. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + 2. Custom driver config object is created here for using 'SubQueryConversion = true'. + + Confirmed bug on 5.0.2.1497. + Checked on 5.0.2.1499-5fa4ae6. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, NetProtocol + +db = db_factory() + +act = python_act('db', substitutions = [ ('[ \t]+',' ') ]) + +test_sql = """ + select /* TRACE_ME */ first 5 1 x + from sales s + where exists ( + select 1 from customer c + where + s.cust_no = c.cust_no + and ( s.cust_no = c.cust_no + or + s.cust_no = c.cust_no + ) + ); +""" + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0.2,<6') +def test_1(act: Action, capsys): + + srv_cfg = driver_config.register_server(name = 'test_srv_gh_8252', config = '') + db_cfg_name = f'db_cfg_8252' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = 'employee' + db_cfg_object.config.value = f""" + SubQueryConversion = true + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + for r in cur.execute(ps): + print(r[0]) + con.rollback() + + + act.expected_stdout = """ + SubQueryConversion true + Sub-query + ....-> Filter + ........-> Table "CUSTOMER" as "C" Access By ID + ............-> Bitmap + ................-> Index "RDB$PRIMARY22" Unique Scan + Select Expression + ....-> First N Records + ........-> Filter + ............-> Table "SALES" as "S" Full Scan + 1 + 1 + 1 + 1 + 1 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From ca83a1bfa6c6972c7545f3f68b90a89c818c4d61 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Sep 2024 12:29:43 +0300 Subject: [PATCH 0174/1064] Added/Updated tests\bugs\gh_5589_test.py: Checked on 6.0.0.457, 5.0.2.1499 --- tests/bugs/gh_5589_test.py | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/bugs/gh_5589_test.py diff --git a/tests/bugs/gh_5589_test.py b/tests/bugs/gh_5589_test.py new file mode 100644 index 00000000..0ff18e81 --- /dev/null +++ b/tests/bugs/gh_5589_test.py @@ -0,0 +1,58 @@ +#coding:utf-8 + +""" +ID: issue-5589 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5589 +TITLE: Support full SQL standard character string literal syntax [CORE5312] +DESCRIPTION: +JIRA: CORE-5312 +NOTES: + [15.09.2024] pzotov + Commit (13.05.2021): + https://github.com/FirebirdSQL/firebird/commit/8a7927aac4fef3740e54b7941146b6d044b864b1 + + Checked on 6.0.0.457, 5.0.2.1499 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set blob all; + set list on; + select 'ab' 'cd' 'ef' as good_chr_01 from rdb$database; + select 'ab'/*comment*/ 'cd' /**/ 'ef' as good_chr_02 from rdb$database; + select 'ab'/* foo + bar */'cd' + '' + /* + */ + + 'ef' as good_chr_03 from rdb$database; + + select 'ab' -- foo + 'cd' -- bar + 'ef' as good_chr_04 from rdb$database; + + select'ab' + 'cd' + 'ef' as good_chr_05 from rdb$database; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +expected_stdout = """ + GOOD_CHR_01 abcdef + GOOD_CHR_02 abcdef + GOOD_CHR_03 abcdef + GOOD_CHR_04 abcdef + GOOD_CHR_05 abcdef +""" + +@pytest.mark.version('>=5.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From aee78b8b69d6d728f2e6acab000e4aac526c3369 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Sep 2024 12:30:15 +0300 Subject: [PATCH 0175/1064] Added/Updated tests\bugs\gh_5588_test.py: Minor change: fixed typo. --- tests/bugs/gh_5588_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_5588_test.py b/tests/bugs/gh_5588_test.py index 2e998242..d7fa1b7e 100644 --- a/tests/bugs/gh_5588_test.py +++ b/tests/bugs/gh_5588_test.py @@ -2,8 +2,8 @@ """ ID: issue-5588 -ISSUE: 5588 -TITLE: upport full SQL standard binary string literal syntax +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5588 +TITLE: Support full SQL standard binary string literal syntax [CORE5311] DESCRIPTION: JIRA: CORE-5311 FBTEST: bugs.gh_5588 From 6fced132bb525a90a812cb935a620aec6c631001 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 16 Sep 2024 16:18:32 +0300 Subject: [PATCH 0176/1064] Added .zip that is needed for upcoming test --- files/gh_8115.zip | Bin 0 -> 4130 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_8115.zip diff --git a/files/gh_8115.zip b/files/gh_8115.zip new file mode 100644 index 0000000000000000000000000000000000000000..9a549d65118994de0428168f1e62330d3dca6b2c GIT binary patch literal 4130 zcmV+-5Z&)kO9KQH000080IGd3Szt%41cna)002$^01E&B0B2}lI59CbE@onDq*!Th z+CUKX+QueLlipRUeu;YD<**I(o55~t6-UV*=*6%zbSG)W$i zlw#(;2uelE#6ffb$tFr!ak)HH(jd8*!Hf*VXxu3>@;S&-h#5JbhnOP&$QooR@w4cF zMbE_PHy|dNkR>0dzXUNF_sCiXvgo{Pp`m3Vi@~pDQH2uP@yu!q|C$ZQ z^qq@j2TTXMQSp2bcbUKi8HtW12AkUs`HnUCbwYH5e7;RS-zU$wuzi~v(soD?U6LV13R1{! zvt|eQY`83L!m@zL3+8@{%zewU{qX#k!2GA*`eH{}G7fFNsX0OvX=J)?c&n7X)-P%<6d6Dpbao$G7Rx2TglvM8CKpb;O!O| zGaQRJV#U~4;=&^?qzD)Cc*#VTWx@l(?kx@04F;p^7gliMhB%1_M~teD+pJcdSJ4?$ z2kvw@bo$h8j$xOwBx*MZLi`}UrcuQo9PxxFEzvF9ojkeI7_JsP zQ47kSv$M06Mu#x88B9z9qZ#z5S1HQtIP6ttc%>{Hoe81h=1~6rl&ty(1tXy6*?*{C zBib)PQ?H1OdI#3iB9wYVK;Q+YK-ps|l)WX11?EbbP$P|Hi%c;^Dqh2R{l(MGL93Jg1>SoGOSx&LW+wO3t;#wMlmhRGCxHx3QD`%wc5X^S;h&2a*zdqofZ&{ zc%tcaBwN7$fpU!Y|K}@l$xpV~U?=WVuRWsX zSZ4~#65|bqBc50rT>=&B7+e0S|_ z$I!TyGxq)vS;BW$5XkoeE7hnsT`O9-+V6}`rt_uWVC?Dv2ghtv2;Wqvu}KcKjJ

s+~7FGnX~ zdpsEpjt_I4;Yo)YW9+6OHugpHDFRnN2&Z->0#6~90m*XSuPlnnpwl94>Xche>s6~e z_)dj0wn@SgS`Oiqg+o!Y{f+`SFCH`1uNr2BVQf1v)*rPGs58cvxZsMh2ji*7mIb#Eu1eAi&$y`7Qv9FO{J9AGa>hAHc#}X~zsdfh&Ka!skgqA=!7vC*=dV=HiS#-sP&rQqq ze7??geKk4|uWpNa4ehmJmFek&m9}RSO(vfJagSP za5_3=2Hl$M=H^nk0^tUP<_iP$902NtP7oBGx&vsr*=!taX>F~ltvA=IoAtN#>Nd<& z>s##uP1|eiH?}vI(~fE@=qp-Kf46IPy1M5Z`t23|cdOJgbYFLcS>_s`N&vgoZN00% z2OwnaQKaKaKyG>5hU1NLnXlCNkewjMqDkB#QHBk*;Ni(=$2Ek@&u`;Uxgop@VH@yz zBEu}(cX-P(I`|YSyk+;UL@?%jhsW!K>)=`7G8gvs4osuM>v`AUac6o0KB1(39j}~X58krB4e@>Ou{t!|m zh2&v?A4=NvxJZKLj6S1-fEGbl40~x{lYJV3VT zs1z=Y8x1E>L_{1fuwM$bk)YxjV_#H4Z6>He_~0#tt0y>VXDkKVieRso=nQu99iN^- zrGC^7G(0YlNcJaHNY(^C@Is!oj0#pz1-^3%5lHmv>D><8x@+maC4p3aOt<0TS2;Z^ zJ5VXdvdj|DM6wpJS=V=aFt@qJLlnmG@lM{^THIp6;^DkJb6%3gc`cC?LKaw9C?ru97UU~Pl&_(D2U*F6 zl456Lfh>sUxfq6nA>HQQbI$zdod5I8%x}&#b9Y>y_i=jHwvNtlq7KpSyCS28f0;60 z=tCn@kxw6n%);e6cTvmV!{%RsL%?hU=iUIEMzACPbPHKBr096vO?NPds2h%yi8POs zVZ>1`nl~@{(z@t#;{cw+U%|u6(eEqAxU!P1(Q=CG?ntZ3=&Px^6~YraW$=OZoaU*;iSH(9!1@i{83UwnnW7cQsgTf6DdIdpCI{pa>< zlL$7{-Z-d6M?h^II42UMEaeBWAEU%7Fe+MMK_y!Od&!d-l|Tz$t16uuJ5Jlx+l-O_aEQ0xhvnyZ7IFQYBfSCi97^XA^KRLk~0~Tku~J8 z@w>D0DwSGvpCR_f09F^k#iGEYuSw9LwW=w`r_9f~?$PEK4d;u>zA`p;V|E@>4wy@T z-eUlaLPAhhfx^;PVY0UD=iu_MSo$53 zIM#z5$9jUPzjaD7`S5zztv!9_G(F_lewKdezV6c7*&DL(jypW@U58U*WdHBF)hExK zx=b^#3zxQ^I(O>z=k7S7(S(5`TSt+N+Wr9D4I?oVNjHepxV$Z6Rl5iL6#==GlW=*S zgsYr{58`ajSR_Qu0x+8bKKlx}_+Ych2ECdB6`NBpdm%yOssMXh?RDuvI~97QHGM8! z_wwc|9{=jM@y`oBfKeuJR%bwTJ-EnzvZ^v>#3aR(quhv3&D+aP!ax`WU@R9w7w+7u z4?xm8?GiFbhzXch5?T5FZ(+;K^zTqi&*@4NV~F4Bn2sfMdZs!^6mFJ5TwRHAkcG?a zJ*f32QHj4<$C1*1z~cGNdq|UbDq-W$fZL=~txBNS|{) z@kt+$J|ula`k3?y=~KtQ)EjQUw!5Fin;(w)S;E-8jh}djmFj-(ntptV-0000^000XBBme*a z00000AOHXW00000XJ}tIF)=kRW@2j!03ZMW0000102lyrp0G(a2-^X2p0G(a2-^XU gZKp{#2-^WrO9ci10000100979000254*&oF0QaKLIRF3v literal 0 HcmV?d00001 From e2e9a2b12c4595713df835de299b522658872932 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 16 Sep 2024 16:19:02 +0300 Subject: [PATCH 0177/1064] Added/Updated tests\bugs\gh_8115_test.py: Checked on 6.0.0.457, 5.0.2.1499. NOTE: plans differ in FB 5.x vs 6.x --- tests/bugs/gh_8115_test.py | 99 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tests/bugs/gh_8115_test.py diff --git a/tests/bugs/gh_8115_test.py b/tests/bugs/gh_8115_test.py new file mode 100644 index 00000000..99b68e96 --- /dev/null +++ b/tests/bugs/gh_8115_test.py @@ -0,0 +1,99 @@ +#coding:utf-8 + +""" +ID: issue-8115 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8115 +TITLE: Avoid reading/hashing the inner stream(s) if the leader stream is empty +DESCRIPTION: + Original title: "FB 5.0.0.1306 - unexpected results using LEFT JOIN with When " +NOTES: + [16.09.2024] pzotov + Confirmed bug in 5.0.1.1369-8c31082 (17.03.2024) + Bug was fixed in 5.0.1.1369-bbd35ab (20.03.2024) + Commit: + https://github.com/FirebirdSQL/firebird/commit/bbd35ab07c129e9735f081fcd29172a8187aa8ab + Avoid reading/hashing the inner stream(s) if the leader stream is empty + + Checked on 6.0.0.457, 5.0.2.1499 +""" +import zipfile +from pathlib import Path +import locale +import re + +from firebird.driver import DatabaseError +import pytest +from firebird.qa import * + +db = db_factory() + +substitutions = [('INDEX_\\d+', 'INDEX_nn'),] + +act = python_act('db', substitutions = substitutions) +tmp_fbk = temp_file('gh_8115.tmp.fbk') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0.1') +def test_1(act: Action, tmp_fbk: Path, capsys): + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_8115.zip', at = 'gh_8115.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + act.gbak(switches = ['-rep', str(tmp_fbk), act.db.db_path], combine_output = True, io_enc = locale.getpreferredencoding()) + print(act.stdout) # must be empty + + test_sql = """ + select aa.id, ab.CNP_USER, ab.ID_USER + from sal_inperioada2('7DC51501-0DF2-45BE-93E5-382A541505DE', '15.05.2024') aa + left join user_cnp(aa.cnp, '15.05.2024') ab on ab.CNP_USER = aa.cnp + where ab.ID_USER = '04B23787-2C7F-451A-A12C-309F79D6F13A' + """ + + 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')]) ) + + try: + cur.execute(ps) + for r in cur: + for p in r: + print(p) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + expected_stdout_5x = """ + Select Expression + ....-> Nested Loop Join (inner) + ........-> Procedure "SAL_INPERIOADA2" as "AA" Scan + ........-> Filter + ............-> Filter + ................-> Procedure "USER_CNP" as "AB" Scan + + 000DD4E1-B4D0-4D6E-9D9F-DE9A7D0D6492 + E574F734-CECB-4A8F-B9BE-FAF51BC61FAD + 04B23787-2C7F-451A-A12C-309F79D6F13A + """ + + expected_stdout_6x = """ + Select Expression + ....-> Filter + ........-> Nested Loop Join (inner) + ............-> Procedure "SAL_INPERIOADA2" as "AA" Scan + ............-> Filter + ................-> Procedure "USER_CNP" as "AB" Scan + 000DD4E1-B4D0-4D6E-9D9F-DE9A7D0D6492 + E574F734-CECB-4A8F-B9BE-FAF51BC61FAD + 04B23787-2C7F-451A-A12C-309F79D6F13A + """ + + 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 From e466c9de751368416ffce2b72357ee0bbd4c25b2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Sep 2024 00:15:08 +0300 Subject: [PATCH 0178/1064] Added/Updated tests\bugs\gh_7846_test.py: Checked on 6.0.0.457; 5.0.2.1499; 4.0.5.3136. --- tests/bugs/gh_7846_test.py | 190 +++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tests/bugs/gh_7846_test.py diff --git a/tests/bugs/gh_7846_test.py b/tests/bugs/gh_7846_test.py new file mode 100644 index 00000000..1e7273f6 --- /dev/null +++ b/tests/bugs/gh_7846_test.py @@ -0,0 +1,190 @@ +#coding:utf-8 + +""" +ID: issue-7846 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7846 +TITLE: FB4 can't backup/restore int128-array +DESCRIPTION: + Test checks ability to make b/r of DB with table that has array-based columns of following types: + smallint; integer; bigint; int128; double. +NOTES: + [16.09.2024] pzotov + 1. Confirmed problem with b/r for INT128 on 4.0.4.3021 (dob: 17-nov-2023). + Got after restore: [Decimal('0'), Decimal('0')] (although no errors were during insert origin data). + Expected values: [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')]. + Confirmed fix on 4.0.4.3022 (dob: 19-nov-2023). + 2. Fix for #8100 ("The isc_array_lookup_bounds function returns invalid values...") required in order + this test can pass on FB 5.x and 6.x. + See commits (07-may-2024): + * 5.x: https://github.com/FirebirdSQL/firebird/commit/26ca064202169c0558359fc9ab06b70e827466f0 + * 6.x: https://github.com/FirebirdSQL/firebird/commit/17b007d14f8ccc6cfba0d63a3b2f21622ced20d0 + FB 4.x was not affected by that bug. + 3. INT128 type requires as argument only INTEGER values (from scope -2**127 ... +2**127-1) but NOT decimals. + Rather, NUMERIC / DECIMAL columns allows only Decimal instances. + (letter from Alex, 20.08.2024 16:11, subj: "gh-6544 ("Error writing an array of NUMERIC(24,6)" ) <...>" + 4. DECFLOAT type had a problem in firebird-driver, fixed in v 1.10.5 (26-JUL-2024) + 5. Some features must be implemented in engine and/or in firebird-driver for proper support of NUMERIC datatype + which have big values and use int128 as underlying storage. + Discussed with pcisar, see subj "firebird-driver and its support for FB datatypes", letters since 21-jul-2024. + See also: https://github.com/FirebirdSQL/firebird/issues/6544#issuecomment-2294778138 + + Checked on 6.0.0.457; 5.0.2.1499; 4.0.5.3136. +""" + +import pytest +from firebird.qa import * +from io import BytesIO +from firebird.driver import SrvRestoreFlag, DatabaseError, InterfaceError +from decimal import Decimal +import traceback +import time + +init_script = """ + recreate table test_arr( + id int generated by default as identity constraint test_pk primary key + ,v_smallint smallint[2] + ,v_integer int[2] + ,v_bigint bigint[2] + ,v_int128 int128[2] + ,v_double double precision[2] + ,v_decfloat decfloat[2] + ); +""" +db = db_factory(init = init_script) + +act = python_act('db') + +#-------------------------------------- +def try_insert(con, cur, fld, data): + print(f'\nTrying to add array in {fld}') + try: + print(f'Data: {data}') + with cur.prepare(f"insert into test_arr({fld}) values (?)") as ps: + for x in data: + cur.execute(ps, (x,)) + + cur.execute(f'select {fld} from test_arr order by id desc rows 1') + for r in cur: + for x in r[0]: + print(x, type(x)) + + con.commit() + print('Success.') + #except (ValueError, InterfaceError, DatabaseError) as e: + except Exception as e: + for x in traceback.format_exc().split('\n'): + print(' ',x) +#-------------------------------------- + +@pytest.mark.version('>=4.0.5') +def test_1(act: Action, capsys): + with act.db.connect() as con: + cur = con.cursor() + + # ------------ smallint ------------- + data = [ [32767, -32768] ] + try_insert(con, cur, 'v_smallint', data) + + # ------------ int ------------- + data = [ [2147483647, -2147483648] ] + try_insert(con, cur, 'v_integer', data) + + # ------------ bigint ------------- + data = [ [9223372036854775807, -9223372036854775808] ] + try_insert(con, cur, 'v_bigint', data) + + # ------------ int128 ------------- + # sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 + # ValueError: Incorrect ARRAY field value. + # !! WRONG!! >>> data = [ [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')] ] + # Only INTEGERS must be specified as arguments: + data = [ [170141183460469231731687303715884105727, -170141183460469231731687303715884105728] ] + try_insert(con, cur, 'v_int128', data) + + # ------------ double ------------- + data = [ [-2.2250738585072014e-308, 1.7976931348623158e+308] ] + try_insert(con, cur, 'v_double', data) + + + # ------------ decfloat ------------- + # ValueError: Incorrect ARRAY field value. + # data = [ [Decimal('-1.0E-6143'), Decimal('9.999999999999999999999999999999999E6144')] ] + # data = [ [-1.0E-6143, 9.999999999999999999999999999999999E6144] ] + data = [ [Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')] ] + try_insert(con, cur, 'v_decfloat', data) + + + backup = BytesIO() + with act.connect_server() as srv: + srv.database.local_backup(database=act.db.db_path, backup_stream=backup) + backup.seek(0) + srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags = SrvRestoreFlag.REPLACE) + + with act.db.connect() as con: + cur = con.cursor() + for fld_name in ('v_smallint','v_integer','v_bigint','v_int128','v_double', 'v_decfloat'): + cur.execute(f'select {fld_name} from test_arr') + for r in cur: + # type(r): + if any(r): + print(f'Result after restore for column {fld_name}:') + for p in r: + print(p) + + act.expected_stdout = """ + Trying to add array in v_smallint + Data: [[32767, -32768]] + 32767 + -32768 + Success. + + Trying to add array in v_integer + Data: [[2147483647, -2147483648]] + 2147483647 + -2147483648 + Success. + + Trying to add array in v_bigint + Data: [[9223372036854775807, -9223372036854775808]] + 9223372036854775807 + -9223372036854775808 + Success. + + Trying to add array in v_int128 + Data: [[170141183460469231731687303715884105727, -170141183460469231731687303715884105728]] + 170141183460469231731687303715884105727 + -170141183460469231731687303715884105728 + Success. + + Trying to add array in v_double + Data: [[-2.2250738585072014e-308, 1.7976931348623157e+308]] + -2.2250738585072014e-308 + 1.7976931348623157e+308 + Success. + + Trying to add array in v_decfloat + Data: [[Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')]] + -9.999999999999999999999999999999999E+6144 + 9.999999999999999999999999999999999E+6144 + Success. + + Result after restore for column v_smallint: + [32767, -32768] + + Result after restore for column v_integer: + [2147483647, -2147483648] + + Result after restore for column v_bigint: + [9223372036854775807, -9223372036854775808] + + Result after restore for column v_int128: + [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')] + + Result after restore for column v_double: + [-2.2250738585072014e-308, 1.7976931348623157e+308] + + Result after restore for column v_decfloat: + [Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')] + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From c6c322001b37952d267cc2efb31d87257b63adc0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 00:08:10 +0300 Subject: [PATCH 0179/1064] Added/Updated tests\bugs\core_0986_test.py: dummy change in order to force all FB versions to be checked by subsequent QA run --- tests/bugs/core_0986_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_0986_test.py b/tests/bugs/core_0986_test.py index f13595fd..5aed18ef 100644 --- a/tests/bugs/core_0986_test.py +++ b/tests/bugs/core_0986_test.py @@ -9,7 +9,7 @@ FBTEST: bugs.core_0986 NOTES: [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). + Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc) """ import pytest From a3cbdc9ece04231ea403de6be79963d6be013243 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 12:14:48 +0300 Subject: [PATCH 0180/1064] Added pre-defined alias required for bugs/gh_8253_test.py --- files/qa-databases.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index ab590f5a..cf6c7d58 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -274,6 +274,13 @@ tmp_gh_6416_alias = $(dir_sampleDb)/qa/tmp_gh_6416.fdb DataTypeCompatibility = 3.0 } +# https://github.com/FirebirdSQL/firebird/issues/8253 +tmp_gh_8253_alias = $(dir_sampleDb)/qa/tmp_gh_8253.fdb +{ + SecurityDatabase = tmp_gh_8253_alias +} + + # Databases for replication tests: # db_main_alias = $(dir_sampleDb)/qa_replication/db_main.fdb From cb6ed4b2ebe0346294eb09e42544003088fba324 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 12:15:12 +0300 Subject: [PATCH 0181/1064] Added/Updated tests\bugs\gh_8253_test.py: Checked on 6.0.0.466, 5.0.2.1513, 4.0.6.3156 --- tests/bugs/gh_8253_test.py | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/bugs/gh_8253_test.py diff --git a/tests/bugs/gh_8253_test.py b/tests/bugs/gh_8253_test.py new file mode 100644 index 00000000..95725df2 --- /dev/null +++ b/tests/bugs/gh_8253_test.py @@ -0,0 +1,112 @@ +#coding:utf-8 + +""" +ID: issue-8253 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8253 +TITLE: Incorrect handling of non-ASCII object names in CREATE MAPPING statement +DESCRIPTION: + Test uses pre-created databases.conf which has alias (see variable REQUIRED_ALIAS) and SecurityDatabase in its details + which points to that alias, thus making such database be self-security. + Database file for that alias must NOT exist in the QA_root/files/qa/ subdirectory: it will be created here. + Self-security database allows us to create GLOBAL mapping without worrying about how it will be removed on test finish. +NOTES: + [23.09.2024] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + 3. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + 4. Confirmed bug on 6.0.0.461, data from rdb$auth_mapping.rdb$map_from: + * is displayed as '???...???' for global mapping; + * is mojibake for local mapping when group name is enclosed in double quotes. + + Checked on 6.0.0.466, 5.0.2.1513, 4.0.6.3156 +""" + +import re +from pathlib import Path + +import pytest +from firebird.qa import * + +REQUIRED_ALIAS = 'tmp_gh_8062_alias' + +db = db_factory() + +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +tmp_sql = temp_file('tmp_8253_non_ascii_ddl.sql') +tmp_log = temp_file('tmp_8253_non_ascii_ddl.log') + +@pytest.mark.intl +@pytest.mark.version('>=4.0.6') +def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_8253_alias = $(dir_sampleDb)/qa/tmp_qa_8253.fdb + # - then we extract filename: 'tmp_qa_8253.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + dba_pswd = 'alterkey' + g_name = 'лондонский симфонический оркестр' + r_name = 'настройщик роялей' + non_ascii_ddl = f''' + set list on; + create database '{REQUIRED_ALIAS}' user {act.db.user}; + create user {act.db.user} password '{dba_pswd}'; + commit; + connect 'localhost:{REQUIRED_ALIAS}' user {act.db.user} password '{dba_pswd}'; + select mon$sec_database from mon$database; -- must be: 'Self' + create role "{r_name}"; + commit; + create mapping "локальная_апостроф" using any plugin from group '{g_name}' to role "{r_name}"; + create mapping "локальная_кавычки" using any plugin from group "{g_name}" to role "{r_name}"; + create global mapping "глобальная_апостроф" using any plugin from group '{g_name}' to role "{r_name}"; + create global mapping "глобальная_кавычки" using any plugin from group "{g_name}" to role "{r_name}"; + commit; + set count on; + select rdb$map_name,rdb$map_from,rdb$map_to from rdb$auth_mapping order by rdb$map_name; + commit; + ''' + + tmp_sql.write_bytes(non_ascii_ddl.encode('cp866')) + act.isql(switches=['-q'], input_file=tmp_sql, credentials = False, connect_db = False, combine_output = True, charset='dos866', io_enc = 'cp866') + tmp_log.write_bytes(act.clean_stdout.encode('utf-8')) + with open(tmp_log, 'r', encoding = 'utf-8', errors = 'backslashreplace') as f: + for line in f: + print(line) + + act.expected_stdout = f""" + MON$SEC_DATABASE Self + RDB$MAP_NAME глобальная_апостроф + RDB$MAP_FROM {g_name} + RDB$MAP_TO {r_name} + RDB$MAP_NAME глобальная_кавычки + RDB$MAP_FROM {g_name} + RDB$MAP_TO {r_name} + RDB$MAP_NAME локальная_апостроф + RDB$MAP_FROM {g_name} + RDB$MAP_TO {r_name} + RDB$MAP_NAME локальная_кавычки + RDB$MAP_FROM {g_name} + RDB$MAP_TO {r_name} + Records affected: 4 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From 6c67c080a416aed872c269fe7a65d65aaf5d84b8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 18:07:17 +0300 Subject: [PATCH 0182/1064] Added/Updated tests\bugs\gh_8255_test.py: Checked on 6.0.0.466, 5.0.2.1513, 4.0.6.3156 --- tests/bugs/gh_8255_test.py | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/bugs/gh_8255_test.py diff --git a/tests/bugs/gh_8255_test.py b/tests/bugs/gh_8255_test.py new file mode 100644 index 00000000..d779589e --- /dev/null +++ b/tests/bugs/gh_8255_test.py @@ -0,0 +1,54 @@ +#coding:utf-8 + +""" +ID: issue-8255 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8255 +TITLE: Catch possible stack overflow when preparing and compiling user statements +DESCRIPTION: + Test generates SQL like 'select 1+1+1....+1 from rdb$database' and tries to execte it. + Exception 'SQLSTATE = HY001 / Stack overflow' must raise instead of crash (that was before fix). + Commits: + * 4.x: https://github.com/FirebirdSQL/firebird/commit/04c586d4ea4bafb50818bcf7f46188afc67ab1c5 (20-sep-2024) + * 5.x: https://github.com/FirebirdSQL/firebird/commit/f0670f90cc7d1fc93db22336fd43abc6d348e31e (18-sep-2024) + * 6.x: https://github.com/FirebirdSQL/firebird/commit/6b445c0dc53f1c5778258bd673c0b61f6dd93a69 (20-sep-2024) +NOTES: + [23.09.2024] pzotov + Initially query containing 15'000 terms in "+1+1...+1" expression used to check. + This query causes 'stack overflow' only in FB 5.x and 6.x. + But in FB 4.0.6.3156 it successfully COMPLETES calculation and issues result. + For FB 4.x this 'threshold' is 16'287 (last number of terms where FB can evaluate result w/o 'stack overflow'). + Because of this, it was decided to increase number of terms to 50'000. + + Checked on 6.0.0.466, 5.0.2.1513, 4.0.6.3156 +""" + +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db', substitutions=[('[ \t]+', ' '), ('After line \\d+.*', '')]) + +tmp_sql = temp_file('tmp_8255_non_ascii_ddl.sql') + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action, tmp_sql: Path, capsys): + + long_expr = '\n'.join( ( + 'select' + ,'+'.join( ('1') * 100000 ) + ,'from rdb$database;' + ) + ) + + tmp_sql.write_bytes(long_expr.encode('utf-8')) + + act.isql(switches=['-q'], input_file=tmp_sql, combine_output = True, charset='win1251') + + act.expected_stdout = f""" + Statement failed, SQLSTATE = HY001 + Stack overflow. The resource requirements of the runtime stack have exceeded the memory available to it. + """ + assert act.clean_stdout == act.clean_expected_stdout + From bdb69722a784a902ff13ea96dd9daa6b2ef0d737 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 18:12:26 +0300 Subject: [PATCH 0183/1064] Added/Updated tests\bugs\gh_8255_test.py: added skipif(platform.system() = 'Windows' according to ticket note about IFDEF WIN_NT. --- tests/bugs/gh_8255_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_8255_test.py b/tests/bugs/gh_8255_test.py index d779589e..bcba0f9e 100644 --- a/tests/bugs/gh_8255_test.py +++ b/tests/bugs/gh_8255_test.py @@ -32,6 +32,7 @@ tmp_sql = temp_file('tmp_8255_non_ascii_ddl.sql') +@pytest.mark.skipif(platform.system() != 'Windows', reason='See ticket note.') @pytest.mark.version('>=4.0.6') def test_1(act: Action, tmp_sql: Path, capsys): From ede28525bd57e9f196745620711a6e9332270fcf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 21:48:58 +0300 Subject: [PATCH 0184/1064] Added/Updated tests\bugs\gh_8255_test.py: fixed forgotten import --- tests/bugs/gh_8255_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8255_test.py b/tests/bugs/gh_8255_test.py index bcba0f9e..78e553e3 100644 --- a/tests/bugs/gh_8255_test.py +++ b/tests/bugs/gh_8255_test.py @@ -23,7 +23,7 @@ """ from pathlib import Path - +import platform import pytest from firebird.qa import * From 25530f80bb708717ce9a6e28b4d46c375c03bca1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Sep 2024 23:59:10 +0300 Subject: [PATCH 0185/1064] Added/Updated tests\bugs\gh_7904_test.py: Changed substitutions: one need to suppress '(keys: N, total key length: M)' in FB 6.x after commit c50b0aa6 ('Add key info to the hash join plan output'). --- tests/bugs/gh_7904_test.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_7904_test.py b/tests/bugs/gh_7904_test.py index 274f0666..77cd52fc 100644 --- a/tests/bugs/gh_7904_test.py +++ b/tests/bugs/gh_7904_test.py @@ -8,6 +8,14 @@ NOTES: Confirmed problem on 5.0.0.1291 (for UMOWA_ROWS = 700K number of fetches = 6059386, elapsed time = 9.609s) Checked on 5.0.0.1303, 6.0.0.180 (for UMOWA_ROWS = 700K number of fetches = 270208, elapsed time = 0.741s) + + [24.09.2024] pzotov + Changed substitutions: one need to suppress '(keys: N, total key length: M)' in FB 6.x (and ONLY there), + otherwise actual and expected output become differ. + Commit: https://github.com/FirebirdSQL/firebird/commit/c50b0aa652014ce3610a1890017c9dd436388c43 + ("Add key info to the hash join plan output", 23.09.2024 18:26) + Discussed with dimitr. + Checked on 6.0.0.467-cc183f5, 5.0.2.1513 """ import pytest @@ -16,6 +24,7 @@ UMOWA_ROWS = 7000 ROZL_MULTIPLIER = 10 + init_sql = f""" set bail on; @@ -178,9 +187,20 @@ commit; """ +#----------------------------------------------------------- db = db_factory(init = init_sql) +substitutions = \ + [ + ( r'\(record length: \d+, key length: \d+\)', '' ) # (record length: 132, key length: 16) + ,( r'\(keys: \d+, total key length: \d+\)', '' ) # (keys: 1, total key length: 2) + ] + +act = python_act('db', substitutions = substitutions) + +#----------------------------------------------------------- + query_lst = [ # Query from https://github.com/FirebirdSQL/firebird/issues/7904: """ @@ -207,9 +227,6 @@ """, ] -substitutions = [ ('record length: \\d+.*', 'record length'), ('key length: \\d+.*', 'key length') ] -act = python_act('db', substitutions = substitutions) - #--------------------------------------------------------- def replace_leading(source, char="."): stripped = source.lstrip() From 9d34fda5313ff92b248c9fcd3fb66041a347d767 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Sep 2024 00:01:37 +0300 Subject: [PATCH 0186/1064] Added/Updated tests\functional\arno\optimizer\test_opt_inner_join_05.py: Changed substitutions: one need to suppress '(keys: N, total key length: M)' in FB 6.x after commit c50b0aa6 ('Add key info to the hash join plan output'). --- .../arno/optimizer/test_opt_inner_join_05.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_05.py index f08ea254..4abba726 100644 --- a/tests/functional/arno/optimizer/test_opt_inner_join_05.py +++ b/tests/functional/arno/optimizer/test_opt_inner_join_05.py @@ -13,6 +13,14 @@ https://github.com/FirebirdSQL/firebird/commit/ae427762d5a3e740b69c7239acb9e2383bc9ca83 // FB 5.x ("More realistic cardinality adjustments for unmatchable booleans, this should also fix #7904: FB5 bad plan for query") Letter from dimitr, 15.12.2023 10:05. + + [24.09.2024] pzotov + Changed substitutions: one need to suppress '(keys: N, total key length: M)' in FB 6.x (and ONLY there), + otherwise actual and expected output become differ. + Commit: https://github.com/FirebirdSQL/firebird/commit/c50b0aa652014ce3610a1890017c9dd436388c43 + ("Add key info to the hash join plan output", 23.09.2024 18:26) + Discussed with dimitr. + Checked on 6.0.0.467-cc183f5, 5.0.2.1513 """ import pytest @@ -308,7 +316,12 @@ db = db_factory(init=init_script) -substitutions = [('record length:\\s+\\d+', 'record length'), ('key length:\\s+\\d+', 'key length') ] +substitutions = \ + [ + ( r'\(record length: \d+, key length: \d+\)', '' ) # (record length: 132, key length: 16) + ,( r'\(keys: \d+, total key length: \d+\)', '' ) # (keys: 1, total key length: 2) + ] + act = python_act('db', substitutions = substitutions) #---------------------------------------------------------- From 7f28961f1b98144402aee8359b194b595870ade4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Sep 2024 07:43:42 +0300 Subject: [PATCH 0187/1064] Added/Updated tests\bugs\gh_8253_test.py: minor change: wrong alias name was in use, changed to correct. --- tests/bugs/gh_8253_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8253_test.py b/tests/bugs/gh_8253_test.py index 95725df2..c184c34f 100644 --- a/tests/bugs/gh_8253_test.py +++ b/tests/bugs/gh_8253_test.py @@ -30,7 +30,7 @@ import pytest from firebird.qa import * -REQUIRED_ALIAS = 'tmp_gh_8062_alias' +REQUIRED_ALIAS = 'tmp_gh_8253_alias' db = db_factory() From a60b8c72cb88a756dd253d033fc02254807c84ff Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Sep 2024 00:09:52 +0300 Subject: [PATCH 0188/1064] Added/Updated tests\functional\tabloid\test_cc183f59.py: Checked on 6.0.0.467. See notes about MERGE JOIN selecting. --- tests/functional/tabloid/test_cc183f59.py | 102 ++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/functional/tabloid/test_cc183f59.py diff --git a/tests/functional/tabloid/test_cc183f59.py b/tests/functional/tabloid/test_cc183f59.py new file mode 100644 index 00000000..c6a537d1 --- /dev/null +++ b/tests/functional/tabloid/test_cc183f59.py @@ -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 From b9c0379c0db23048b2beaa44a3251f6b5b379f07 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Sep 2024 09:35:57 +0300 Subject: [PATCH 0189/1064] Added/Updated tests\bugs\gh_8250_test.py: Checked on 6.0.0.467. NOTE: test currently has min_version=6.0, see notes. --- tests/bugs/gh_8250_test.py | 132 +++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tests/bugs/gh_8250_test.py diff --git a/tests/bugs/gh_8250_test.py b/tests/bugs/gh_8250_test.py new file mode 100644 index 00000000..121a3e6d --- /dev/null +++ b/tests/bugs/gh_8250_test.py @@ -0,0 +1,132 @@ +#coding:utf-8 + +""" +ID: 8250 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8250 +TITLE: Bad performance on simple two joins query on tables with composed index +DESCRIPTION: +NOTES: + [25.09.2024] pzotov + 0. Tables in explained plans are specified in the same order for snapshots before and after fix. + Difference can be seen only in added "keys: " clause. + This clause currently exists only in FB 6.x, commit: + https://github.com/FirebirdSQL/firebird/commit/c50b0aa652014ce3610a1890017c9dd436388c43 + Because of this, test min_version = 6.0. + 1. Improvement can be checked by parsing of explained plan if its top-level hash join looks like + "Hash Join (inner) (keys: N, total key length: ...)" and value of is NOT LESS THAN some + minimal threshold defined by variable MIN_REQUIRED_KEYS_IN_TOP_LEVEL_HJ. + As explained by dimitr, for this test such value must be 5 (letter 24.09.2024 07:22). + 2. Tables must have indices (defined by PK and FK constraints) for explained plan to show 'keys: N' + with N > 1. Otherwise top-level HJ line will be 'keys: 1' and query will run as slow as it was + specified in the ticket. The reason is that in case of missed indices optimizer uses other criteria + for estimation of cost and plan will remain ineffective (at least for current FB 6.x). + Explained by dimitr, letter 24.09.2024 12:29. + + Confirmed problem on 6.0.0.461. + Checked on 6.0.0.467. +""" + +import re +import time + +import pytest +from firebird.qa import * + +MIN_REQUIRED_KEYS_IN_TOP_LEVEL_HJ = 5 +ROWS_LIMIT_FOR_CHILD_TABLES = 5000 + +init_sql = f""" + create table test1(id1 int not null, id2 int not null, name varchar(30) not null); + create table test2(id1 int not null, id2 int not null, code30 varchar(36) not null, descr varchar(36)); + create table test3(id1 int not null, id2 int not null, code30 varchar(36) not null, code15 varchar(15) not null, price double precision); + + set term ^; + execute block as + declare n_cnt int = {ROWS_LIMIT_FOR_CHILD_TABLES}; + declare i int; + declare v_code30 type of column test2.code30; + begin + insert into test1(id1, id2, name) select 1, i, left(uuid_to_char(gen_uuid()), 30) from (select row_number()over()-1 i from rdb$types rows 16); + i = 0; + while (i < n_cnt) do + begin + v_code30 = lpad('', 36, uuid_to_char(gen_uuid())); + insert into test2(id1, id2, code30, descr) values( 1, mod(:i, 4), :v_code30, :v_code30); + insert into test3(id1, id2, code30, code15, price) values( 1, mod(:i, 4) , :v_code30, left(uuid_to_char(gen_uuid()), 15), round(1000)); + i = i + 1; + end + + end + ^ + set term ;^ + commit; + set echo on; + alter table test1 add constraint t1_pk primary key(id1,id2); + alter table test2 add constraint t2_pk primary key(id1,id2,code30); + alter table test3 add constraint t3_pk primary key(id1,id2,code30,code15); +""" +db = db_factory(init = init_sql, page_size = 8192) + +substitutions = [ ('[ \t]+', ' ') + ,('keys: \\d+, total key length: \\d+', 'keys, total key length') + ,('record length: \\d+', 'record 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 1 x + from test2 t2 + join test3 t3 on t3.id1 = t2.id1 and t3.id2 = t2.id2 and t3.code30 = t2.code30 + join test1 t1 on t1.id1 = t2.id1 and t1.id2 = t2.id2 + """ + + # 'Hash Join (inner) (keys: 3, total key length: 38)' + p_hj_keys = re.compile(r'Hash Join \(inner\) \(keys: \d+', re.IGNORECASE) + top_level_keys_found = -1 + 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')]) ) + for s in ps.detailed_plan.split('\n'): + if (pm := p_hj_keys.search(s)): + top_level_keys_found = max(top_level_keys_found, int(pm.group().split()[-1])) + break + + max_keys_msg = 'Top-level hash join keys: ' + expected_keys = '' + if top_level_keys_found >= MIN_REQUIRED_KEYS_IN_TOP_LEVEL_HJ: + max_keys_msg += 'EXPECTED' + expected_keys = max_keys_msg + else: + max_keys_msg += f'UNEXPECTED, {" too low: "+str(top_level_keys_found)+" - less than "+str(MIN_REQUIRED_KEYS_IN_TOP_LEVEL_HJ) if top_level_keys_found > 0 else "NOT FOUND"}' + + print(max_keys_msg) + + act.expected_stdout = f""" + Select Expression + ....-> Filter + ........-> Hash Join (inner) (keys, total key length) + ............-> Hash Join (inner) (keys, total key length) + ................-> Table "TEST3" as "T3" Full Scan + ................-> Record Buffer (record length) + ....................-> Table "TEST1" as "T1" Full Scan + ............-> Record Buffer (record length) + ................-> Table "TEST2" as "T2" Full Scan + {expected_keys} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 44dd2cdb348ba77d4ad5e8e868bc65815af0191e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Sep 2024 10:47:01 +0300 Subject: [PATCH 0190/1064] Added/Updated tests\functional\tabloid\test_aae2ae32.py: Checked on 5.0.2.1516-92316F0 -- all ok: two hash joins instead of subquery. --- tests/functional/tabloid/test_aae2ae32.py | 143 ++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 tests/functional/tabloid/test_aae2ae32.py diff --git a/tests/functional/tabloid/test_aae2ae32.py b/tests/functional/tabloid/test_aae2ae32.py new file mode 100644 index 00000000..1fed532d --- /dev/null +++ b/tests/functional/tabloid/test_aae2ae32.py @@ -0,0 +1,143 @@ +#coding:utf-8 + +""" +ID: issue-8252 +ISSUE: https://github.com/FirebirdSQL/firebird/commit/aae2ae3291855f51ff587d0da055aed270137e8f +TITLE: Better fix for #8252: incorrect subquery unnesting with complex dependencies, it re-allows converting nested IN/EXISTS into multiple semi-join +DESCRIPTION: + Test verifies additional commit related to https://github.com/FirebirdSQL/firebird/issues/8252 + Example #1 from https://github.com/FirebirdSQL/firebird/issues/8265 is used for check + (suggested by dimitr, letter 25.09.2024 13:33) +NOTES: + [26.09.2024] pzotov + 1. No ticket has been created for this test. + 2. Confirmed problem on 5.0.2.1516-fe6ba50 (23.09.2024), got for SubQueryConversion = true plan with subquery: + # Sub-query + # -> Filter + # -> Filter + # -> Hash Join (semi) + # ... and ... + # Select Expression + # -> Aggregate + # -> Filter + # -> Table "TEST1" as "A" Full Scan + 3. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + 4. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + + Checked on 5.0.2.1516-92316F0 -- all ok: two hash joins instead of subquery. + Thanks to dimitr for the advice on implementing the test. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError + +init_script = """ + create table test1(id int not null); + create table test2(id int not null, pid int not null); + create table test3(id int not null, pid int not null, name varchar(30) not null); + commit; + + insert into test1(id) select row_number()over()-1 from rdb$types rows 10; + insert into test2(id, pid) select row_number()over()-1, mod(row_number()over()-1, 10) from rdb$types rows 100; + insert into test3(id, pid, name) select row_number()over()-1, mod(row_number()over()-1, 100), 'QWEABCRTY' from rdb$types, rdb$types rows 1000; + commit; + + -- alter table test1 add constraint test1_pk primary key(id); + -- alter table test2 add constraint test2_pk primary key(id); + -- alter table test3 add constraint test3_pk primary key(id); + -- alter table test2 add constraint test2_fk foreign key(pid) references test1; + -- alter table test3 add constraint test3_fk foreign key(pid) references test2; +""" + +db = db_factory(init=init_script) + +act = python_act('db', substitutions = [('record length: \\d+', 'record length')]) + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0.2,<6') +def test_1(act: Action, capsys): + + test_sql = """ + select count(*) from test1 a + where + a.id in ( + select b.pid from test2 b + where + b.id in ( + select c.pid from test3 c + where name like '%ABC%' + ) + ); + """ + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_aae2ae32_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_aae2ae32_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + try: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # Print data: + for r in cur.execute(ps): + print(r[0]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + act.expected_stdout = f""" + SubQueryConversion true + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (semi) + ................-> Table "TEST1" as "A" Full Scan + ................-> Record Buffer (record length: 82111) + ....................-> Filter + ........................-> Hash Join (semi) + ............................-> Table "TEST2" as "B" Full Scan + ............................-> Record Buffer (record length: 57111) + ................................-> Filter + ....................................-> Table "TEST3" as "C" Full Scan + 10 + + SubQueryConversion false + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "A" Full Scan + 10 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 3fd31597085b3009f44709bddaca69c974cde9e9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Sep 2024 10:48:49 +0300 Subject: [PATCH 0191/1064] Added/Updated tests\bugs\gh_8233_test.py: minor change - fixed typo --- tests/bugs/gh_8233_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8233_test.py b/tests/bugs/gh_8233_test.py index 035df828..31ca0735 100644 --- a/tests/bugs/gh_8233_test.py +++ b/tests/bugs/gh_8233_test.py @@ -3,7 +3,7 @@ """ ID: issue-8233 ISSUE: https://github.com/FirebirdSQL/firebird/issues/8233 -TITLE: SubQueryConversion = true --multiple rows in singleton select +TITLE: SubQueryConversion = true - multiple rows in singleton select DESCRIPTION: NOTES: [27.08.2024] pzotov From a3ba2b7669e3125adaebf15f487c64f02ff5f091 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Sep 2024 10:50:19 +0300 Subject: [PATCH 0192/1064] Added/Updated tests\bugs\gh_8252_test.py: added comment about additional test for this issue: tests/functional/tabloid/test_aae2ae32.py --- tests/bugs/gh_8252_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_8252_test.py b/tests/bugs/gh_8252_test.py index 9f939e1f..2fa5afbf 100644 --- a/tests/bugs/gh_8252_test.py +++ b/tests/bugs/gh_8252_test.py @@ -10,6 +10,7 @@ 1. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 2. Custom driver config object is created here for using 'SubQueryConversion = true'. + 3. Additional test was made for this issue: tests/functional/tabloid/test_aae2ae32.py Confirmed bug on 5.0.2.1497. Checked on 5.0.2.1499-5fa4ae6. From 05df68c160a73fc5a99d324fd68e239ef05fbe62 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Sep 2024 11:28:54 +0300 Subject: [PATCH 0193/1064] Added/Updated tests\bugs\gh_8265_test.py: Checked on 5.0.2.1516-92316F0 (intermediate snapshot 25.09.2024) --- tests/bugs/gh_8265_test.py | 270 +++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 tests/bugs/gh_8265_test.py diff --git a/tests/bugs/gh_8265_test.py b/tests/bugs/gh_8265_test.py new file mode 100644 index 00000000..679239d7 --- /dev/null +++ b/tests/bugs/gh_8265_test.py @@ -0,0 +1,270 @@ +#coding:utf-8 + +""" +ID: issue-8265 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8265 +TITLE: Nested IN/EXISTS subqueries should not be converted into semi-joins if the outer context is a sub-query which wasn't unnested +DESCRIPTION: +NOTES: + [26.09.2024] pzotov + 0. ::: NB ::: This test probably will be reimplemented later, see note by dimitr in the ticket: + "In the future this heuristics should be replaced with a cost-based approach between hash and nested loop semi-join" + 1. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. + Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + 2. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + 3. First example of this test is also used in tests/functional/tabloid/test_aae2ae32.py + + Confirmed problem on 5.0.2.1516-fe6ba50 (23.09.2024). + Checked on 5.0.2.1516-92316F0 (25.09.2024). +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError + +init_script = """ + create table test1(id int not null); + create table test2(id int not null, pid int not null); + create table test3(id int not null, pid int not null, name varchar(30) not null); + commit; + + insert into test1(id) select row_number()over()-1 from rdb$types rows 10; + insert into test2(id, pid) select row_number()over()-1, mod(row_number()over()-1, 10) from rdb$types rows 100; + insert into test3(id, pid, name) select row_number()over()-1, mod(row_number()over()-1, 100), 'QWEABCRTY' from rdb$types, rdb$types rows 1000; + commit; +""" + +db = db_factory(init=init_script) + +act = python_act('db', substitutions = [('record length: \\d+', 'record length')]) + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0.2,<6') +def test_1(act: Action, capsys): + + test_query_lst = [ + """ + -- Example 1: both sub-queries can (and should) be unnested. + select count(*) from test1 q1_a + where + q1_a.id in ( + select q1_b.pid from test2 q1_b + where + q1_b.id in ( + select q1_c.pid from test3 q1_c + where q1_c.name like '%ABC%' + ) + ) + """, + """ + -- Example 2: inner sub-query cannot be unnested due to OR condition present, but the outer sub-query can + select count(*) from test1 q2_a + where + q2_a.id in ( + select q2_b.pid from test2 q2_b + where + 1=1 or q2_b.id in ( + select q2_c.pid from test3 q2_c + where q2_c.name like '%ABC%' + ) + ) + """, + """ + -- Example-3: outer sub-query cannot be unnested due to OR condition present, so the inner sub-query should NOT be unnested too. + select count(*) from test1 q3_a + where + 1=1 or q3_a.id in ( + select q3_b.pid from test2 q3_b + where q3_b.id in ( + select id from test3 q3_c + where q3_c.name like '%ABC%' + ) + ) + """, + """ + -- Example-4: both sub-queries can NOT be unnested due to OR conditions present. + select count(*) from test1 q4_a + where + 1=1 or q4_a.id in ( + select id from test2 q4_b + where + 1=1 or q4_b.id in ( + select id from test3 q4_c + where q4_c.name like '%ABC%' + ) + ) + """ + ] + + + for sq_conv in ('true','false',): + srv_cfg = driver_config.register_server(name = f'srv_cfg_aae2ae32_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_aae2ae32_{sq_conv}' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + SubQueryConversion = {sq_conv} + """ + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + for idx, test_sql in enumerate(test_query_lst): + try: + cur = con.cursor() + cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") + for r in cur: + print(r[0],r[1]) + + ps = cur.prepare(test_sql) + + print(f'\nExample {idx+1}') + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # Print data: + for r in cur.execute(ps): + print(r[0]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + + act.expected_stdout = f""" + SubQueryConversion true + Example 1 + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (semi) + ................-> Table "TEST1" as "Q1_A" Full Scan + ................-> Record Buffer (record length) + ....................-> Filter + ........................-> Hash Join (semi) + ............................-> Table "TEST2" as "Q1_B" Full Scan + ............................-> Record Buffer (record length) + ................................-> Filter + ....................................-> Table "TEST3" as "Q1_C" Full Scan + 10 + + SubQueryConversion true + Example 2 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q2_C" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (semi) + ................-> Table "TEST1" as "Q2_A" Full Scan + ................-> Record Buffer (record length) + ....................-> Filter + ........................-> Table "TEST2" as "Q2_B" Full Scan + 10 + + SubQueryConversion true + Example 3 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q3_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q3_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q3_A" Full Scan + 10 + + SubQueryConversion true + Example 4 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q4_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q4_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q4_A" Full Scan + 10 + + + SubQueryConversion false + Example 1 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q1_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q1_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q1_A" Full Scan + 10 + + SubQueryConversion false + Example 2 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q2_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q2_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q2_A" Full Scan + 10 + + SubQueryConversion false + Example 3 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q3_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q3_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q3_A" Full Scan + 10 + + SubQueryConversion false + Example 4 + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST3" as "Q4_C" Full Scan + Sub-query + ....-> Filter + ........-> Filter + ............-> Table "TEST2" as "Q4_B" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" as "Q4_A" Full Scan + 10 + + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 89e3f717f8d7ffed2e0357953247b4df9d7ee700 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Sep 2024 11:31:15 +0300 Subject: [PATCH 0194/1064] Added/Updated tests\bugs\gh_8265_test.py: added comment --- tests/bugs/gh_8265_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_8265_test.py b/tests/bugs/gh_8265_test.py index 679239d7..7b1f4979 100644 --- a/tests/bugs/gh_8265_test.py +++ b/tests/bugs/gh_8265_test.py @@ -9,6 +9,7 @@ [26.09.2024] pzotov 0. ::: NB ::: This test probably will be reimplemented later, see note by dimitr in the ticket: "In the future this heuristics should be replaced with a cost-based approach between hash and nested loop semi-join" + (https://github.com/FirebirdSQL/firebird/issues/8265#issue-2546991823) 1. Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 2. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. From ebc90eff4812f0ca06ebefc94d03cfc4eef3f0a8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Sep 2024 08:46:23 +0300 Subject: [PATCH 0195/1064] Added/Updated tests\bugs\gh_8265_test.py: fixed wrong value of argument for 'driver_config.register_server()' call that caused another test fail with 'Server ... already registered' --- tests/bugs/gh_8265_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8265_test.py b/tests/bugs/gh_8265_test.py index 7b1f4979..891e0d76 100644 --- a/tests/bugs/gh_8265_test.py +++ b/tests/bugs/gh_8265_test.py @@ -106,8 +106,8 @@ def test_1(act: Action, capsys): for sq_conv in ('true','false',): - srv_cfg = driver_config.register_server(name = f'srv_cfg_aae2ae32_{sq_conv}', config = '') - db_cfg_name = f'db_cfg_aae2ae32_{sq_conv}' + srv_cfg = driver_config.register_server(name = f'srv_cfg_8265_{sq_conv}', config = '') + db_cfg_name = f'db_cfg_8265_{sq_conv}' db_cfg_object = driver_config.register_database(name = db_cfg_name) db_cfg_object.server.value = srv_cfg.name db_cfg_object.database.value = str(act.db.db_path) From dbcd5e8067df26e6efeb4a371e88f1e042c9ff33 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Sep 2024 17:11:28 +0300 Subject: [PATCH 0196/1064] Increased ParallelWorkers: it must be greater than 1 because of tests/gh_8263_test.py - see notes there --- configs/fb50_all.conf | 4 ++-- configs/fb60_all.conf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/fb50_all.conf b/configs/fb50_all.conf index 850fcda1..fa264e6b 100644 --- a/configs/fb50_all.conf +++ b/configs/fb50_all.conf @@ -78,8 +78,8 @@ ClientBatchBuffer = 131072 SnapshotsMemSize = 64K TipCacheBlockSize = 4M -# Added 03-apr-2023: -ParallelWorkers = 1 +# ParallelWorkers must be GREATER than 1 since 28.09.2024, see bugs/gh_8263_test.py +ParallelWorkers = 2 MaxParallelWorkers = 8 # SubQueryConversion = false diff --git a/configs/fb60_all.conf b/configs/fb60_all.conf index 679b1edd..4519f757 100644 --- a/configs/fb60_all.conf +++ b/configs/fb60_all.conf @@ -78,8 +78,8 @@ ClientBatchBuffer = 131072 SnapshotsMemSize = 64K TipCacheBlockSize = 4M -# Added 03-apr-2023: -ParallelWorkers = 1 +# ParallelWorkers must be GREATER than 1 since 28.09.2024, see bugs/gh_8263_test.py +ParallelWorkers = 2 MaxParallelWorkers = 8 #OptimizeForFirstRows = false From f9366e45561b914c737b71b78b57c84e035d867a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Sep 2024 17:19:19 +0300 Subject: [PATCH 0197/1064] Added/Updated tests\bugs\gh_8263_test.py: Checked on 6.0.0.474, 5.0.2.1519. SEE NOTES. --- tests/bugs/gh_8263_test.py | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/bugs/gh_8263_test.py diff --git a/tests/bugs/gh_8263_test.py b/tests/bugs/gh_8263_test.py new file mode 100644 index 00000000..df739190 --- /dev/null +++ b/tests/bugs/gh_8263_test.py @@ -0,0 +1,145 @@ +#coding:utf-8 + +""" +ID: issue-8263 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8263 +TITLE: gbak on Classic with ParallelWorkers > 1 doesn't restore indices, giving a cryptic error message +DESCRIPTION: + Following conditions must be met to reproduce ticket issue: + * firebird.conf contains ParallelWorkers > 1 and MaxParallelWorkers >= ParallelWorkers; + * test database has a table with indexed column and number of POINTER PAGES more than 1. + Test creates table with PK-column (type = int) and wide text column ('data_filler') of len = . + We add records into this table and make backup of this table. + Set ROWS_COUNT = 50'000 and DATA_FILLER_WID = 1'000 leads to allocating 5 pointer pages for test table + (database must be created with page_size = 8192). + + Then we run restore WITHOUT '-par' switch and without verbosing. + Before fix this issued error described in the ticket and index remained inactive. + After fix this restore must complete silently (w/o any output). + Finally, we run query that must use PK index and compare its explained plan with expected which must contain + 'Index "..." Full Scan' line. +NOTES: + [28.09.2024] pzotov + ::: NB ::: + This test forced to change prototypes of firebird.conf for 5.x and 6.x, see in $QA_HOME/firebird-qa/configs/ + files 'fb50_all.conf' and 'fb60_all.conf': they now contain ParallelWorkers > 1. + This change may affect on entire QA run result! Some other tests may need to be adjusted after this. + + Thanks to Vlad for suggestions about this test implementation. + + Confirmed bug on 6.0.0.471, 5.0.2.1516 + Checked on 6.0.0.474, 5.0.2.1519 -- all Ok. +""" +import locale +from pathlib import Path +import time + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, DatabaseError, SrvRestoreFlag + +tmp_fbk = temp_file('tmp_gh_8263.fbk') +tmp_fdb = temp_file('tmp_gh_8263_restored.tmp') + +######################### +### S E T T I N G S ### +######################### +ROWS_COUNT = 50000 +DATA_FILLER_WID = 1000 + +init_script = f""" + create table test( + id int generated by default as identity -- constraint pk_wares primary key using index test_pk + ,data_filler varchar({DATA_FILLER_WID}) + ); + commit; + + set term ^; + execute block as + declare n int = {ROWS_COUNT}; + begin + while (n>0) do + begin + insert into test(data_filler) values( lpad('', {DATA_FILLER_WID}, uuid_to_char(gen_uuid())) ); + n = n - 1; + end + end + ^ + set term ;^ + commit; + create index test_id on test(id); + commit; +""" + +db = db_factory(init = init_script, page_size = 8192) + +act = python_act('db') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + if act.vars['server-arch'].lower() != 'classic': + pytest.skip('Only Classic was affected.') + + #srv_cfg = driver_config.register_server(name = f'srv_cfg_8263', config = '') + #db_cfg_name = f'db_cfg_8263' + #db_cfg_object = driver_config.register_database(name = db_cfg_name) + #db_cfg_object.server.value = srv_cfg.name + #db_cfg_object.database.value = str(act.db.db_path) + ## db_cfg_object.parallel_workers.value = 3 + + with act.db.connect() as con: # connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + chk_sql = """ + select + max(iif(rdb$config_name = 'ServerMode', rdb$config_value, null)) as srv_mode + ,cast(max(iif(rdb$config_name = 'ParallelWorkers', rdb$config_value, null)) as int) as par_workers + ,cast(max(iif(rdb$config_name = 'MaxParallelWorkers', rdb$config_value, null)) as int) as max_workers + from rdb$config + """ + cur = con.cursor() + cur.execute(chk_sql) + srv_mode, par_workers, max_workers = cur.fetchone() + assert srv_mode == 'Classic', f'Not applicable ServerMode: {srv_mode}' + assert par_workers > 1, f'ParallelWorkers = {par_workers} must be greater than 1 for this test' + assert max_workers > par_workers, f'MaxParallelWorkers = {maxworkers} must be greater than ParallelWorkers = {par_workers}' + + act.gfix(switches=['-shutdown','single', '-force', '0', act.db.dsn]) + print(act.stdout) # must be empty + + act.gbak(switches=['-b', act.db.dsn, str(tmp_fbk)], combine_output = True, io_enc = locale.getpreferredencoding()) + print(act.stdout) # must be empty + + # BEFORE fix following restore failed with: + # gbak:cannot commit index TEST_ID + # gbak: ERROR:invalid database handle (no active connection) + # gbak: ERROR:Database is not online due to failure to activate one or more indices. + # gbak: ERROR: Run gfix -online to bring database online without active indices. + # + act.gbak(switches=['-rep', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) + print(act.stdout) # must be empty! + + ############################################################### + + with connect(str(tmp_fdb), user = act.db.user, password = act.db.password) as con: + chk_sql = 'select 1 from test order by id' + cur = con.cursor() + ps = cur.prepare(chk_sql) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + act.expected_stdout = f""" + Select Expression + ....-> Table "TEST" Access By ID + ........-> Index "TEST_ID" Full Scan + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + \ No newline at end of file From c4e2af9b2c4fc52ba214a0a5c24919a447c444ad Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Sep 2024 01:40:30 +0300 Subject: [PATCH 0198/1064] Added .zip that is needed for upcoming test bugs/gh_7398_test.py --- files/gh_7398.zip | Bin 0 -> 188626 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_7398.zip diff --git a/files/gh_7398.zip b/files/gh_7398.zip new file mode 100644 index 0000000000000000000000000000000000000000..f367ca151e72e1bf7f1bb86dc045ffc7b4f2b957 GIT binary patch literal 188626 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%0DNLqhf(I`Ir0>?jM9@U<1N0W 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

!tD5{v*NED|whC?s-}s2C2r-MVlOARx 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

)h*F!{47W+C{ae9`8jf9eQw>XH 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 Date: Sun, 29 Sep 2024 01:40:58 +0300 Subject: [PATCH 0199/1064] Added/Updated tests\bugs\gh_7398_test.py: Checked on 6.0.0.471, 5.0.2.1519, 4.0.6.3157. SEE NOTES. --- tests/bugs/gh_7398_test.py | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tests/bugs/gh_7398_test.py diff --git a/tests/bugs/gh_7398_test.py b/tests/bugs/gh_7398_test.py new file mode 100644 index 00000000..830480ce --- /dev/null +++ b/tests/bugs/gh_7398_test.py @@ -0,0 +1,155 @@ +#coding:utf-8 + +""" +ID: issue-7398 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7398 +TITLE: Worst plan sort created to execute an indexed tables +DESCRIPTION: +NOTES: + [29.09.2024] pzotov + 1. Ineffective execution plan was up to 4.0.3.2840. + Since 4.0.3.2843 plan changed and is the same for all subsequent FB-4.x snapshots. + Commit: https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 + (13.09.2022 19:17, "More complete solution for #3357 and #7118") + + 2. Database provided in the ticket has too big size (~335 Mb). + Test uses much smaller DB that was created on basis of original one by + extraction of small portions of data from tables PCP_TIN_REC_MAT and INV_ETQ_MAT. + These tables in original DB have 114115 and 1351211 rows. + In DB that is used here these tables have 15000 and 30000 rows corresp. + NOT all constraints are used in the test DB. Particularly, following DDL were abandoned: + ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_EMP FOREIGN KEY (ID_EMP) REFERENCES SYS_EMP (ID_EMP); + ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_OP FOREIGN KEY (ID_OP) REFERENCES PCP_OP (ID_OP); + ALTER TABLE PCP_TIN_REC_MAT ADD CONSTRAINT FK_PCP_TIN_REC_MAT_MAT FOREIGN KEY (ID_MAT) REFERENCES INV_MAT (ID_MAT); + Test database have been backed up using 4.0.3.2840 and compressed to .zip file. + 3. Because of missed valuable part of source data, I'm not sure that this test verifies exactly ticket issue. + But in any case, using this test one may see difference in execution plan that is produced in 4.0.3.2840 and 4.0.3.2843. + And such difference also can be seen on original DB (although plans there differ from those which are in test DB). + + Checked on 6.0.0.471, 5.0.2.1519, 4.0.6.3157. +""" + +import locale +import re +import zipfile +from pathlib import Path +from firebird.driver import SrvRestoreFlag +import time + +import pytest +from firebird.qa import * + +db = db_factory() + +act = python_act('db') + +check_sql = """ + select r.id_op, r.id_rec, sum(m.q_mat * cus.cus_med) + from pcp_tin_rec r + join pcp_tin_rec_mat m on r.id_rec = m.id_rec + join inv_etq_mat cus on cus.id_mat = m.id_mat and cus.anomes = r.am_bai + join inv_etq_nat nat on nat.id_nat = cus.id_nat + where + nat.cml_stat = 1 and r.id_op = 216262 + group by r.id_op, r.id_rec +""" + +fbk_file = temp_file('gh_7398.tmp.fbk') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +expected_out_4x = """ + Select Expression + ....-> Aggregate + ........-> Sort (record length: 148, key length: 16) + ............-> Nested Loop Join (inner) + ................-> Filter + ....................-> Table "PCP_TIN_REC" as "R" Full Scan + ................-> Filter + ....................-> Table "PCP_TIN_REC_MAT" as "M" Access By ID + ........................-> Bitmap + ............................-> Index "FK_PCP_TIN_REC_MAT_REC" Range Scan (full match) + ................-> Filter + ....................-> Table "INV_ETQ_MAT" as "CUS" Access By ID + ........................-> Bitmap + ............................-> Index "IDX_INV_ETQ_MAT_ANOMES" Range Scan (full match) + ................-> Filter + ....................-> Table "INV_ETQ_NAT" as "NAT" Access By ID + ........................-> Bitmap + ............................-> Index "PK_INV_ETQ_NAT" Unique Scan +""" +expected_out_5x = """ + Select Expression + ....-> Aggregate + ........-> Sort (record length: 148, key length: 16) + ............-> Filter + ................-> Hash Join (inner) + ....................-> Nested Loop Join (inner) + ........................-> Filter + ............................-> Table "PCP_TIN_REC" as "R" Full Scan + ........................-> Filter + ............................-> Table "PCP_TIN_REC_MAT" as "M" Access By ID + ................................-> Bitmap + ....................................-> Index "FK_PCP_TIN_REC_MAT_REC" Range Scan (full match) + ........................-> Filter + ............................-> Table "INV_ETQ_MAT" as "CUS" Access By ID + ................................-> Bitmap + ....................................-> Index "IDX_INV_ETQ_MAT_ANOMES" Range Scan (full match) + ....................-> Record Buffer (record length: 33) + ........................-> Filter + ............................-> Table "INV_ETQ_NAT" as "NAT" Access By ID + ................................-> Bitmap + ....................................-> Index "IDX_INV_ETQ_NAT_CML_STAT" Range Scan (full match) +""" +expected_out_6x = """ + Select Expression + ....-> Aggregate + ........-> Sort (record length: 148, key length: 16) + ............-> Filter + ................-> Hash Join (inner) (keys: 1, total key length: 4) + ....................-> Nested Loop Join (inner) + ........................-> Filter + ............................-> Table "PCP_TIN_REC" as "R" Full Scan + ........................-> Filter + ............................-> Table "PCP_TIN_REC_MAT" as "M" Access By ID + ................................-> Bitmap + ....................................-> Index "FK_PCP_TIN_REC_MAT_REC" Range Scan (full match) + ........................-> Filter + ............................-> Table "INV_ETQ_MAT" as "CUS" Access By ID + ................................-> Bitmap + ....................................-> Index "IDX_INV_ETQ_MAT_ANOMES" Range Scan (full match) + ....................-> Record Buffer (record length: 33) + ........................-> Filter + ............................-> Table "INV_ETQ_NAT" as "NAT" Access By ID + ................................-> Bitmap + ....................................-> Index "IDX_INV_ETQ_NAT_CML_STAT" Range Scan (full match) +""" + +@pytest.mark.version('>=4.0') +def test_1(act: Action, fbk_file: Path, capsys): + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_7398.zip', at = 'gh_7398.fbk') + fbk_file.write_bytes(zipped_fbk_file.read_bytes()) + + with act.connect_server(encoding=locale.getpreferredencoding()) as srv: + srv.database.restore(database = act.db.db_path, backup = fbk_file, flags = SrvRestoreFlag.REPLACE) + restore_log = srv.readlines() + assert restore_log == [] + + + with act.db.connect() as con: + chk_sql = 'select 1 from test order by id' + cur = con.cursor() + ps = cur.prepare(check_sql) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + act.expected_stdout = expected_out_4x if act.is_version('<5') else expected_out_5x if act.is_version('<6') else expected_out_6x + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From f85816beb953f695b59d67f360140ce867a93a21 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Sep 2024 01:47:07 +0300 Subject: [PATCH 0200/1064] Added/Updated tests\bugs\gh_7118_test.py: added comment about related commit --- tests/bugs/gh_7118_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/bugs/gh_7118_test.py b/tests/bugs/gh_7118_test.py index e0a222bc..3088a9c3 100644 --- a/tests/bugs/gh_7118_test.py +++ b/tests/bugs/gh_7118_test.py @@ -6,6 +6,11 @@ TITLE: Chained JOIN .. USING across the same column names may be optimized badly NOTES: [01.03.2023] pzotov + Commit related to this test: + https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 + (13.09.2022 19:17, "More complete solution for #3357 and #7118") + One more test that attempts to verify this commit: bugs/gh_7398_test.py + Checked on 3.0.11.33665, 4.0.3.2904, 5.0.0.964 """ From a26e1cce6b881e431d8fb929598648e62bf2f0fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Sep 2024 01:47:19 +0300 Subject: [PATCH 0201/1064] Added/Updated tests\bugs\gh_3357_test.py: added comment about related commit --- tests/bugs/gh_3357_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_3357_test.py b/tests/bugs/gh_3357_test.py index 89b469b4..e73fc608 100644 --- a/tests/bugs/gh_3357_test.py +++ b/tests/bugs/gh_3357_test.py @@ -6,12 +6,17 @@ TITLE: Bad execution plan if some stream depends on multiple streams via a function [CORE2975] NOTES: [04.03.2023] pzotov - Discussed with dimitr, letters 01-mar-2023 18:37 and 04-mar-2023 10:38. + 1. Discussed with dimitr, letters 01-mar-2023 18:37 and 04-mar-2023 10:38. Test must verify that execution plan uses NESTED LOOPS rather than HASH JOIN. Because of this, tables must be filled with approximately equal volume of data. Confirmed bug on 3.0.9.33548 (28-dec-2021), plan was: PLAN HASH (JOIN (T1 INDEX (T1_COL), T2 INDEX (T2_ID)), T3 NATURAL) - Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. + 2. Commit related to this test: + https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 + (13.09.2022 19:17, "More complete solution for #3357 and #7118") + One more test that attempts to verify this commit: bugs/gh_7398_test.py + + Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. """ import pytest From 25dd99989daebfc1ec3d0707d1fe83763a94fea4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Sep 2024 23:11:41 +0300 Subject: [PATCH 0202/1064] Added/Updated tests\bugs\core_4345_test.py: added combine_ouput=True in order to see failed details in annotations. --- tests/bugs/core_4345_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4345_test.py b/tests/bugs/core_4345_test.py index 3a324582..7dcd4620 100644 --- a/tests/bugs/core_4345_test.py +++ b/tests/bugs/core_4345_test.py @@ -101,7 +101,7 @@ def test_1(act: Action): """ # Case 1: Trace functions enabled with act.trace(db_events=trace): - act.isql(switches=['-n', '-q'], input=func_script % (123, 456)) + act.isql(switches=['-n', '-q'], input=func_script % (123, 456), combine_output = True) # for line in act.trace_log: if (func_start_ptn.search(line) @@ -112,7 +112,7 @@ def test_1(act: Action): # Case 2: Trace functions disabled act.trace_log.clear() with act.trace(db_events=trace[:-2]): - act.isql(switches=['-n', '-q'], input=func_script % (789, 987)) + act.isql(switches=['-n', '-q'], input=func_script % (789, 987), combine_output = True) # for line in act.trace_log: if (func_start_ptn.search(line) From 063602005b0caab1bc0dbbaabdd6742dbabaa7e2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 22 Oct 2024 20:29:09 +0300 Subject: [PATCH 0203/1064] Added/Updated tests\bugs\gh_8249_test.py: Checked on 6.0.0.485 -- all OK. No output to STDOUT, all queries finish with errors. --- tests/bugs/gh_8249_test.py | 127 +++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tests/bugs/gh_8249_test.py diff --git a/tests/bugs/gh_8249_test.py b/tests/bugs/gh_8249_test.py new file mode 100644 index 00000000..30009f1d --- /dev/null +++ b/tests/bugs/gh_8249_test.py @@ -0,0 +1,127 @@ +#coding:utf-8 + +""" +ID: issue-8249 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8249 +TITLE: CAST() ignores collation of target data type +NOTES: + [22.10.2024] pzotov + Commit related to this test (04.10.2024 13:13): + https://github.com/FirebirdSQL/firebird/commit/aa167e2b36122684796d7b34935b0340be6f5074 + See also: gh_7748_test.py + + Confirmed problem on 6.0.0.483: queries to view, function, SP and EB complete OK (rather than expectedly raise error). + Checked on 6.0.0.485 -- all OK. No output to STDOUT, all queries finish with errors. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + create view v_test_1 as + select cast('x' as varchar(10) character set utf8 collate missed_coll) as view_output from rdb$database + ; + commit; + + set term ^; + create procedure sp_test_1 returns(sp_output varchar(10) character set utf8) as + begin + sp_output = cast('x' as varchar(10) character set utf8 collate missed_coll); + suspend; + end + ^ + create procedure sp_test_2 returns(sp_output varchar(10) character set utf8) as + declare v_text varchar(10) character set utf8; + begin + v_text = cast('x' as varchar(10) character set utf8 collate missed_coll); + sp_output = v_text; + suspend; + end + ^ + create function fn_test_1 returns varchar(10) character set utf8 as + begin + return cast('x' as varchar(10) character set utf8 collate missed_coll); + end + ^ + set term ;^ + commit; + + select * from v_test_1; + select fn_test_1() as fn_output from rdb$database; + select * from sp_test_1; + + set term ^; + execute block returns(eb_text varchar(10) character set utf8) as + begin + execute procedure sp_test_2 returning_values :eb_text; + suspend; + end + ^ + set term ;^ + +""" + +act = isql_act('db', test_script, substitutions = [('[-]?At line \\d+.*', '')]) + +expected_stdout = """ + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE VIEW V_TEST_1 failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION MISSED_COLL for CHARACTER SET UTF8 is not defined + + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE PROCEDURE SP_TEST_1 failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION MISSED_COLL for CHARACTER SET UTF8 is not defined + + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE PROCEDURE SP_TEST_2 failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION MISSED_COLL for CHARACTER SET UTF8 is not defined + + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE FUNCTION FN_TEST_1 failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION MISSED_COLL for CHARACTER SET UTF8 is not defined + + Statement failed, SQLSTATE = 42S02 + Dynamic SQL Error + -SQL error code = -204 + -Table unknown + -V_TEST_1 + + Statement failed, SQLSTATE = 39000 + Dynamic SQL Error + -SQL error code = -804 + -Function unknown + -FN_TEST_1 + + Statement failed, SQLSTATE = 42S02 + Dynamic SQL Error + -SQL error code = -204 + -Table unknown + -SP_TEST_1 + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -204 + -Procedure unknown + -SP_TEST_2 +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From c93d02de5f097009c0fac79bd518dc0bde9ca785 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 22 Oct 2024 20:29:33 +0300 Subject: [PATCH 0204/1064] Added/Updated tests\bugs\gh_7748_test.py: added ref to gh_8249_test.py --- tests/bugs/gh_7748_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_7748_test.py b/tests/bugs/gh_7748_test.py index 1b84aec7..5a8963a3 100644 --- a/tests/bugs/gh_7748_test.py +++ b/tests/bugs/gh_7748_test.py @@ -13,6 +13,7 @@ NOTES: [25.11.2023] pzotov Checked on 6.0.0.150. + See also: gh_8249_test.py """ import pytest From d0a66d4f63f118a20196e6bca7f6254f933093ca Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 24 Oct 2024 23:24:50 +0300 Subject: [PATCH 0205/1064] Added/Updated tests\bugs\gh_8241_test.py: dummy change to force QA scenario to check all FB versions. --- tests/bugs/gh_8241_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8241_test.py b/tests/bugs/gh_8241_test.py index 4d54cdcb..8fcd4b5b 100644 --- a/tests/bugs/gh_8241_test.py +++ b/tests/bugs/gh_8241_test.py @@ -7,7 +7,7 @@ NOTES: Restore must use gbak utility, target DB must be prefixed by 'localhost:'. - Confirmed bug on 6.0.0.447, 5.0.2.1487 + Confirmed bug on 6.0.0.447, 5.0.2.1487. Checked on 6.0.0.450-8591572, 5.0.2.1493-eb720e8. """ From debd6ed3fd1481cad9e2a6f384c039eaaa2ed94d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 25 Oct 2024 00:08:12 +0300 Subject: [PATCH 0206/1064] Added/Updated tests\bugs\gh_8290_test.py: Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds). --- tests/bugs/gh_8290_test.py | 154 +++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/bugs/gh_8290_test.py diff --git a/tests/bugs/gh_8290_test.py b/tests/bugs/gh_8290_test.py new file mode 100644 index 00000000..517622dc --- /dev/null +++ b/tests/bugs/gh_8290_test.py @@ -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 From d991658a61188f1f021bbd82fcbfe045b9cff0f5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 25 Oct 2024 01:05:31 +0300 Subject: [PATCH 0207/1064] Added/Updated tests\bugs\gh_8291_test.py: Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds). --- tests/bugs/gh_8291_test.py | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/bugs/gh_8291_test.py diff --git a/tests/bugs/gh_8291_test.py b/tests/bugs/gh_8291_test.py new file mode 100644 index 00000000..701eeb37 --- /dev/null +++ b/tests/bugs/gh_8291_test.py @@ -0,0 +1,82 @@ +#coding:utf-8 + +""" +ID: issue-8291 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8291 +TITLE: NULLs should be skipped during index navigation when there's no lower bound and matched conditions are known to ignore NULLs +DESCRIPTION: + Test uses script from ticket. We compare number of indexed reads with threshold - see variable MAX_ALLOWED_IDX_READS. + BEFORE fix value of indexed was 500002 (both on 5.x and 6.x), after fix it became 886 (using default page_size = 8k). +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 * + +############################ +MAX_ALLOWED_IDX_READS = 1000 +############################ + +init_sql = """ + create table test (id int); + + set term ^; + execute block as + declare n int = 1000000; + declare i int = 0; + begin + while (i < n) do + begin + insert into test(id) values( iif(mod(:i, 2) = 0, null, :i) ); + i = i + 1; + end + end^ + set term ;^ + commit; + + create index test_id on test(id); + commit; +""" +db = db_factory(page_size = 8192, init = init_sql) + +act = python_act('db') + +#----------------------------------------------------------- + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action, capsys): + msg_prefix = 'Number of indexed reads:' + expected_txt = 'EXPECTED' + idx_reads = {} + with act.db.connect() as con: + cur = con.cursor() + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = 'TEST'") + test_rel_id = cur.fetchone()[0] + idx_reads[test_rel_id] = 0 + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == test_rel_id: + idx_reads[test_rel_id] = -x_table.indexed + + cur.execute('select count(*) from (select id from test where id < 3 order by id)') + data = cur.fetchall() + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == test_rel_id: + idx_reads[test_rel_id] += x_table.indexed + + # BEFORE fix value of indexed was 500002. After fix: 886 + if idx_reads[test_rel_id] < MAX_ALLOWED_IDX_READS: + print(f'{msg_prefix} {expected_txt}') + else: + print(f'{msg_prefix} UNEXPECTED: {idx_reads[test_rel_id]} - greater than threshold = {MAX_ALLOWED_IDX_READS}.') + + act.expected_stdout = f""" + {msg_prefix} {expected_txt} + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 8d4f444954776647d6435be66920a53e80897b06 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 25 Oct 2024 13:55:50 +0300 Subject: [PATCH 0208/1064] Added/Updated tests\bugs\gh_8161_test.py: Splitted expected_out after fixed #8290 -- see notes. --- tests/bugs/gh_8161_test.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py index e293c96d..3a1d5fa9 100644 --- a/tests/bugs/gh_8161_test.py +++ b/tests/bugs/gh_8161_test.py @@ -19,6 +19,12 @@ Confirmed bug (regression) on 3.0.12.33735 (date of build: 09-mar-2024). Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374. + + [25.10.2024] pzotov + Splitted expected_out after fixed #8290: 'Index "RDB$INDEX_nn" Range Scan (full match)' must appear in explained plan) + for RDB$PROCEDURES table (index on columns: RDB$PACKAGE_NAME,RDB$PROCEDURE_NAME - is unique and at least one of these + columns allow NULLs). + Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds). """ import zipfile from pathlib import Path @@ -79,7 +85,7 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ps = cur.prepare(test_sql) print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - expected_stdout = """ + expected_stdout_4x = """ Select Expression ....-> Singularity Check ........-> Aggregate @@ -98,6 +104,27 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ............-> Bitmap ................-> Index "RDB$INDEX_3" Range Scan (full match) """ - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + Select Expression + ....-> Singularity Check + ........-> Aggregate + ............-> Nested Loop Join (inner) + ................-> Filter + ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_nn" Range Scan (full match) + ................-> Filter + ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_nn" Range Scan (full match) + Select Expression + ....-> Filter + ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID + ............-> Bitmap + ................-> Index "RDB$INDEX_nn" Range Scan (full match) + """ + + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 2c41272f32aa1d9851800d2edd1ec14c37a328c1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 25 Oct 2024 18:58:49 +0300 Subject: [PATCH 0209/1064] Added/Updated tests\bugs\gh_8091_test.py: Checked on 6.0.0.508-67d8e39 (intermediate build). --- tests/bugs/gh_8091_test.py | 144 +++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 tests/bugs/gh_8091_test.py diff --git a/tests/bugs/gh_8091_test.py b/tests/bugs/gh_8091_test.py new file mode 100644 index 00000000..166e48bb --- /dev/null +++ b/tests/bugs/gh_8091_test.py @@ -0,0 +1,144 @@ +#coding:utf-8 + +""" +ID: issue-8091 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8091 +TITLE: Ability to create an inactive index +DESCRIPTION: + Test creates a table with several indices, all of them are specified as INACTIVE. + Then we check that these indices actually can *not* be used: explained plans for any query + to this table that could relate to indexed columns must now contain 'Full Scan'. + After this we extract metadata (with saving it to 'init_meta' variable) and drop test table. + Applying of metada to the test database (which is empty now) must pass without errors and, + more important, all indices must remain inactive after that. + Finally, we change DB dialect to 1, make b/r and again do same actions. + Result must be the same as for iteration with default dialect = 3. +NOTES: + [25.10.2024] pzotov + Checked on 6.0.0.508-67d8e39 (intermediate build). +""" +import time +from io import BytesIO +from firebird.driver import SrvRestoreFlag +import pytest +from firebird.qa import * + +init_sql = """ + set bail on; + recreate table test(id int generated by default as identity, x int, y int, z int); + set term ^; + execute block as + declare n int = 100000; + declare i int = 0; + begin + while (i < n) do + begin + insert into test(x, y, z) values( :i, null, :i); + i = i + 1; + end + end^ + set term ;^ + commit; + + create unique ascending index test_x_asc inactive on test(x); + create descending index test_y_desc inactive on test(y); + create unique descending index test_x_plus_y inactive on test computed by (x+y); + + create index test_z_partial inactive on test(z) where mod(id,2) = 0; + create unique index test_x_minus_y_partial inactive 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 + +#----------------------------------------------------------- + +def check_indices_inactive(act, qry_map, nr_block, capsys): + 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('') + ps.free() + + expected_out = '\n'.join( [''.join( (qry_map[i],'\n',nr_block) ) for i in range(len(qry_map))] ) + act.expected_stdout = expected_out + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + +#----------------------------------------------------------- + +@pytest.mark.version('>=6.0') +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' + } + nr_block = """ + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST" Full Scan + """ + + for iter in range(2): + + # check-1: ensure that all indices actually are INACTIVE, i.e. all queries will use full scan. + ########## + check_indices_inactive(act, qry_map, nr_block, capsys) + + #---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++--- + + # check-2: extract metadata, drop table and apply metadata which now contains 'INACTIVE' clause for indices. + ########## + act.isql(switches=['-x']) + init_meta = '\n'.join( ('set bail on;', act.stdout) ) + + with act.db.connect() as con: + con.execute_immediate('drop table test') + con.commit() + + # Apply metadata to main test database. + act.isql(switches = [], input = init_meta) + # NO errors must occur now: + assert act.clean_stdout == '' + act.reset() + + #---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++---===+++--- + + # check-3: ensure that all indices REMAIN INACTIVE, i.e. all queries will use full scan. + ########## + check_indices_inactive(act, qry_map, nr_block, capsys) + + if iter == 0: + # change dialect to 1, make backup / restore and repeat all prev actions. + act.gfix(switches = ['-sql_dialect', '1', act.db.dsn], combine_output = True) + assert act.clean_stdout == '' + act.reset() + + backup = BytesIO() + with act.connect_server() as srv: + srv.database.local_backup(database = act.db.db_path, backup_stream = backup) + backup.seek(0) + srv.database.local_restore(backup_stream = backup, database = act.db.db_path, flags = SrvRestoreFlag.REPLACE) From df802f3bfcf256d1aa0909eeb9e51bdb9a2f9fae Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 26 Oct 2024 11:21:35 +0300 Subject: [PATCH 0210/1064] Added/Updated tests\bugs\gh_8290_test.py: added ps.free() call otherwise pytest hangs at final point and does not return control to caller batch --- tests/bugs/gh_8290_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/bugs/gh_8290_test.py b/tests/bugs/gh_8290_test.py index 517622dc..d0efda58 100644 --- a/tests/bugs/gh_8290_test.py +++ b/tests/bugs/gh_8290_test.py @@ -65,6 +65,10 @@ def test_1(act: Action, capsys): print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) print('') + # 26.10.2024. ::: ACHTUNG ::: + # MANDATORY OTHERWISE PYTEST WILL HANG AT FINAL POINT: + ps.free() + expected_out = f""" {qry_map[0]} From 38bdbb14efd5abf7ca63c42138ca68c291173e92 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 28 Oct 2024 14:21:51 +0300 Subject: [PATCH 0211/1064] Added/Updated tests\bugs\core_1725_test.py: fully re-implemented - see notes. --- tests/bugs/core_1725_test.py | 505 +++++++++++++++++++++++------------ 1 file changed, 341 insertions(+), 164 deletions(-) diff --git a/tests/bugs/core_1725_test.py b/tests/bugs/core_1725_test.py index 52844ff5..ef821291 100644 --- a/tests/bugs/core_1725_test.py +++ b/tests/bugs/core_1725_test.py @@ -5,100 +5,119 @@ ISSUE: 2149 TITLE: Unable to restore a database with inactive indices if any SP/trigger contains an explicit plan DESCRIPTION: + We create table and indices for it. + Then we create trigger for this table, view, procedure, function and package - and all of them have DDL + which explicitly uses 'TEST ORDER ' in execution plan. + Such database then backed up and restored with command switch '-i(nactive)'. + Restore is logged and we check that this log does not contain 'gbak:error' message (and eventually completes OK). + Restored database must contain all created DB objects, i.e. we must have ability to explicitly specify them in SQL. + Table trigger (containing explicit PLAN clause in its DDL) also must exist and remain active. + + Before this bug was fixed: + 1) log of restore contained: + gbak: ERROR:Error while parsing function FN_WORKER's BLR + gbak: ERROR: index TEST_X cannot be used in the specified plan + 2) restored database had NO indices that were explicitly specified in any DDL and any attempt to use appropriate + DB object failed with SQLSTATE = 42S02/39000/42000 ('Table/Procedure/Function} unknown'). + JIRA: CORE-1725 FBTEST: bugs.core_1725 +NOTES: + [28.10.2024] pzotov + 1. Test fully re-implemented. + We do NOT extract metadata before and after restore (in order to compare it): + in FB 6.x 'gbak -i' leads to 'create INACTIVE index ...' statements in generated SQL + (see https://github.com/FirebirdSQL/firebird/issues/8091 - "Ability to create an inactive index"). + + Comparison of metadata that was before and after restore has no much sense. + Rather, we have to check SQL/DML that attempt to use DB object which DDL contain + explicitly specified execution plan. + All such actions must raise error related to invalid BLR, but *not* error about missing DB object. + + BTW: it looks strange that such messages contain "-there is no index TEST_X for table TEST". + Such index definitely DOES exist but it is inactive. + + 2. Bug existed up to 17-jan-2019. + It was fixed by commits related to other issues, namely: + 3.x: a74130019af89012cc1e04ba18bbc9c4a69e1a5d // 17.01.2019 + 4.x: fea7c61d9741dc142fa020bf3aa93af7e52e2002 // 17.01.2019 + 5.x: fea7c61d9741dc142fa020bf3aa93af7e52e2002 // 18.01.2019 + ("Attempted to fix CORE-2440, CORE-5118 and CORE-5900 together (expression indices contain NULL keys after restore).") + + Checked on: + 6.0.0.511-c4bc943; 5.0.2.1547-1e08f5e; 4.0.0.1384-fea7c61 (17-jan-2019, just after fix); 3.0.13.33793-3e62713 """ -import pytest -from firebird.qa import * -from firebird.driver import SrvRestoreFlag, SrvRepairFlag -from io import BytesIO +import locale +import re +from collections import defaultdict from difflib import unified_diff +from pathlib import Path -substitutions_1 = [('[ \t]+', ' ')] +import pytest +from firebird.qa import * init_script = """ -set bail on; - -create or alter procedure sp_init as begin end; -create or alter procedure sp_main as begin end; -create or alter procedure sp_worker as begin end; - -create or alter function fn_init returns int as begin end; -create or alter function fn_main returns int as begin end; -create or alter function fn_worker returns int as begin end; - - -create table test(id int primary key, x int, y int); -create index test_x on test(x); -create descending index test_y on test(y); -commit; - -insert into test(id, x, y) select row_number()over(), rand()*5, rand()*100 from rdb$types; -commit; - -create or alter view v_init as - select count(*) as cnt from test group by x - rows 1 -; - -create or alter view v_worker as - select count(*) as cnt - from test - group by y - plan (TEST ORDER TEST_Y) - union all - select cnt from v_init -; -commit; - - -set term ^; -execute block as -begin - rdb$set_context('USER_SESSION','INITIAL_DDL', '1'); -end -^ - -create or alter procedure sp_init as - declare c int; -begin - select count(*) from test group by x - rows 1 - into c + set bail on; + + create or alter procedure sp_init as begin end; + create or alter procedure sp_main as begin end; + create or alter procedure sp_worker as begin end; + + create or alter function fn_init returns int as begin end; + create or alter function fn_main returns int as begin end; + create or alter function fn_worker returns int as begin end; + + create table test(id int primary key, x int, y int); + create index test_x on test(x); + create descending index test_y on test(y); + commit; + + insert into test(id, x, y) select row_number()over(), rand()*5, rand()*100 from rdb$types; + commit; + + create or alter view v_init as + select count(*) as cnt from test group by x + rows 1 ; -end -^ - -create or alter procedure sp_main as -begin - execute procedure sp_worker; -end -^ - -create or alter procedure sp_worker as - declare c int; -begin - select sum(cnt) - from ( + + create or alter view v_worker as select count(*) as cnt - from test group by x - plan (TEST ORDER TEST_X) + from test + group by y + plan (TEST ORDER TEST_Y) union all - select cnt from v_worker - ) - into c + select cnt from v_init ; -end -^ -create or alter function fn_init returns int as -begin - return ( select count(*) from test ); -end -^ -create or alter function fn_worker returns int as -begin - return ( + commit; + + + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION','INITIAL_DDL', '1'); + end + ^ + + create or alter procedure sp_init as + declare c int; + begin + select count(*) from test group by x + rows 1 + into c + ; + end + ^ + + create or alter procedure sp_main as + begin + execute procedure sp_worker; + end + ^ + + create or alter procedure sp_worker as + declare c int; + begin select sum(cnt) from ( select count(*) as cnt @@ -107,24 +126,16 @@ union all select cnt from v_worker ) - ); -end -^ -create or alter function fn_main returns int as -begin - return fn_worker(); -end -^ - -create or alter package pg_test as -begin - function pg_fn_worker returns int; - procedure pg_sp_worker; -end -^ -recreate package body pg_test as -begin - function pg_fn_worker returns int as + into c + ; + end + ^ + create or alter function fn_init returns int as + begin + return ( select count(*) from test ); + end + ^ + create or alter function fn_worker returns int as begin return ( select sum(cnt) @@ -137,81 +148,247 @@ ) ); end + ^ + create or alter function fn_main returns int as + begin + return fn_worker(); + end + ^ - procedure pg_sp_worker as - declare c int; + create or alter package pg_test as begin - select sum(cnt) - from ( - select count(*) as cnt - from test group by x - plan (TEST ORDER TEST_X) - union all - select cnt from v_worker - ) - into c - ; + function pg_fn_worker returns int; + procedure pg_sp_worker; end + ^ + recreate package body pg_test as + begin + function pg_fn_worker returns int as + begin + return ( + select sum(cnt) + from ( + select count(*) as cnt + from test group by x + plan (TEST ORDER TEST_X) + union all + select cnt from v_worker + ) + ); + end -end -^ + procedure pg_sp_worker as + declare c int; + begin + select sum(cnt) + from ( + select count(*) as cnt + from test group by x + plan (TEST ORDER TEST_X) + union all + select cnt from v_worker + ) + into c + ; + end -create or alter trigger trg_attach active on connect position 0 as - declare c int; -begin - if ( rdb$get_context('USER_SESSION','INITIAL_DDL') is null ) then + end + ^ + create or alter trigger test_bi for test active before insert position 0 as + declare c int; begin - select sum(cnt) - from ( - select count(*) as cnt - from test group by x - plan (TEST ORDER TEST_X) - union all - select cnt from v_worker - ) - into c; + if ( rdb$get_context('USER_SESSION','INITIAL_DDL') is null ) then + begin + select sum(cnt) + from ( + select count(*) as cnt + from test group by x + plan (TEST ORDER TEST_X) + union all + select cnt from v_worker + ) + into c; + end end -end -^ -set term ;^ -commit; + ^ + set term ;^ + commit; """ -db = db_factory(init=init_script) +substitutions = [('[ \t]+', ' '), ('(-)?invalid request BLR at offset \\d+', 'invalid request BLR at offset')] + +db = db_factory(init = init_script) +act = python_act('db', substitutions = substitutions) -act = python_act('db') +tmp_fbk= temp_file('tmp_core_1725.fbk') +tmp_fdb = temp_file('tmp_core_1725.fdb') @pytest.mark.version('>=3.0.6') -def test_1(act: Action): - # Extract metadata from initial DB - act.isql(switches=['-nod', '-x']) - meta_1 = act.stdout +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + outcomes_map = defaultdict(str) + + act.gbak(switches=['-b', act.db.dsn, str(tmp_fbk)]) + + # restore _WITHOUT_ building indices: + act.gbak(switches=['-rep', '-i', '-v', str(tmp_fbk), str(tmp_fdb) ], combine_output = True, io_enc = locale.getpreferredencoding()) + + watching_patterns = [re.compile(x, re.IGNORECASE) for x in (r'gbak:\s?ERROR(:)?\s?', r'gbak:finis.*\s+going home', r'gbak:adjust.*\s+flags')] + + for line in act.clean_stdout.splitlines(): + for p in watching_patterns: + if p.search(line): + outcomes_map['restore_log'] += line+'\n' + act.reset() + + ########################################################################### + + check_metadata = """ + set list on; + set count on; + + select ri.rdb$index_name, ri.rdb$index_inactive from rdb$indices ri where ri.rdb$relation_name = upper('test') and ri.rdb$index_name starting with upper('test'); + + select p.rdb$package_name, p.rdb$procedure_name as sp_name, p.rdb$valid_blr as sp_valid_blr + from rdb$procedures p + where p.rdb$system_flag is distinct from 1 + order by p.rdb$package_name, p.rdb$procedure_name + ; + + select f.rdb$package_name, f.rdb$function_name as fn_name, f.rdb$valid_blr as fn_valid_blr + from rdb$functions f + where f.rdb$system_flag is distinct from 1 + order by f.rdb$package_name, f.rdb$function_name + ; + + select rt.rdb$trigger_name, rt.rdb$trigger_inactive, rt.rdb$valid_blr as tg_valid_blr + from rdb$triggers rt + where + rt.rdb$system_flag is distinct from 1 and + rt.rdb$relation_name = upper('test') + ; + + set count off; + """ + act.isql(switches=['-nod', '-q', str(tmp_fdb)], input = check_metadata, credentials = True, charset = 'utf8', connect_db = False, combine_output = True, io_enc = locale.getpreferredencoding()) + for line in act.clean_stdout.splitlines(): + outcomes_map['check_metadata'] += line+'\n' + act.reset() + + ########################################################################### + + check_avail_db_objects = """ + set list on; + set echo on; + select * from v_worker; + + execute procedure sp_main; + + select fn_main() from rdb$database; + + execute procedure pg_test.pg_sp_worker; + + select pg_test.pg_fn_worker() from rdb$database; + + insert into test(id, x, y) values(-1, -1, -1) returning id, x, y; + """ + act.isql(switches=['-nod', '-q', str(tmp_fdb)], input = check_avail_db_objects, credentials = True, charset = 'utf8', connect_db = False, combine_output = True, io_enc = locale.getpreferredencoding()) + + for line in act.clean_stdout.splitlines(): + outcomes_map['check_avail_db_objects'] += line+'\n' act.reset() - # backup + restore _WITHOUT_ building indices: - backup = BytesIO() - with act.connect_server() as srv: - srv.database.local_backup(database=act.db.db_path, backup_stream=backup) - backup.seek(0) - srv.database.local_restore(backup_stream=backup, database=act.db.db_path, - flags=SrvRestoreFlag.DEACTIVATE_IDX | SrvRestoreFlag.REPLACE) - # Get FB log before validation, run validation and get FB log after it: - log_before = act.get_firebird_log() - srv.database.repair(database=act.db.db_path, flags=SrvRepairFlag.CORRUPTION_CHECK) - #act.gfix(switches=['-v', '-full', act.db.dsn]) - log_after = act.get_firebird_log() - # Extract metadata from restored DB - act.isql(switches=['-nod', '-x']) - meta_2 = act.stdout + + for k,v in outcomes_map.items(): + print(k) + for p in v.splitlines(): + print(p) + print('') + + ########################################################################### + + act.expected_stdout = """ + restore_log + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + + check_metadata + RDB$INDEX_NAME TEST_X + RDB$INDEX_INACTIVE 1 + RDB$INDEX_NAME TEST_Y + RDB$INDEX_INACTIVE 1 + Records affected: 2 + + RDB$PACKAGE_NAME + SP_NAME SP_INIT + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_MAIN + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_WORKER + SP_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + SP_NAME PG_SP_WORKER + SP_VALID_BLR 1 + Records affected: 4 + + RDB$PACKAGE_NAME + FN_NAME FN_INIT + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_MAIN + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_WORKER + FN_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + FN_NAME PG_FN_WORKER + FN_VALID_BLR 1 + Records affected: 4 + + RDB$TRIGGER_NAME TEST_BI + RDB$TRIGGER_INACTIVE 0 + TG_VALID_BLR 1 + Records affected: 1 + + check_avail_db_objects + select * from v_worker; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset 35 + -there is no index TEST_Y for table TEST + + execute procedure sp_main; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure SP_MAIN's BLR + -Error while parsing procedure SP_WORKER's BLR + -invalid request BLR at offset 66 + -there is no index TEST_X for table TEST + + select fn_main() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function FN_MAIN's BLR + -Error while parsing function FN_WORKER's BLR + -invalid request BLR at offset 72 + -there is no index TEST_X for table TEST + + execute procedure pg_test.pg_sp_worker; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure PG_TEST.PG_SP_WORKER's BLR + -invalid request BLR at offset 66 + -there is no index TEST_X for table TEST + + select pg_test.pg_fn_worker() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function PG_TEST.PG_FN_WORKER's BLR + -invalid request BLR at offset 72 + -there is no index TEST_X for table TEST + + insert into test(id, x, y) values(-1, -1, -1) returning id, x, y; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset + -there is no index TEST_X for table TEST + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout act.reset() - # Restore with indices. This is necessary to drop the database safely otherwise connect - # to drop will fail in test treadown as connect trigger referes to index tat was not activated - with act.connect_server() as srv: - backup.seek(0) - srv.database.local_restore(backup_stream=backup, database=act.db.db_path, - flags=SrvRestoreFlag.REPLACE) - # - diff_meta = ''.join(unified_diff(meta_1.splitlines(), meta_2.splitlines())) - diff_log = [line for line in unified_diff(log_before, log_after) if line.startswith('+') and 'Validation finished:' in line] - # Checks - assert diff_meta == '' - assert diff_log == ['+\tValidation finished: 0 errors, 0 warnings, 0 fixed\n'] From e72e2163186fc08097ccae2966f7d32691cfd308 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 29 Oct 2024 14:06:39 +0300 Subject: [PATCH 0212/1064] Added/Updated tests\bugs\gh_8255_test.py: added/adjusted comments. Tes can run currently only on Windows. On Linux server stil crashes. --- tests/bugs/gh_8255_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_8255_test.py b/tests/bugs/gh_8255_test.py index 78e553e3..835532b7 100644 --- a/tests/bugs/gh_8255_test.py +++ b/tests/bugs/gh_8255_test.py @@ -13,11 +13,16 @@ * 6.x: https://github.com/FirebirdSQL/firebird/commit/6b445c0dc53f1c5778258bd673c0b61f6dd93a69 (20-sep-2024) NOTES: [23.09.2024] pzotov - Initially query containing 15'000 terms in "+1+1...+1" expression used to check. + Initially query contained expression of 15'000 terms ("1+1+1...+1") was used to check. This query causes 'stack overflow' only in FB 5.x and 6.x. But in FB 4.0.6.3156 it successfully COMPLETES calculation and issues result. For FB 4.x this 'threshold' is 16'287 (last number of terms where FB can evaluate result w/o 'stack overflow'). - Because of this, it was decided to increase number of terms to 50'000. + Because of this, it was decided to increase number of terms to 100'000. + + ::: NB ::: + Fix currently exists only for Windows, see: + https://github.com/FirebirdSQL/firebird/pull/8255#issuecomment-2354781108 + On Linux this query still crashes server. Checked on 6.0.0.466, 5.0.2.1513, 4.0.6.3156 """ @@ -32,7 +37,7 @@ tmp_sql = temp_file('tmp_8255_non_ascii_ddl.sql') -@pytest.mark.skipif(platform.system() != 'Windows', reason='See ticket note.') +@pytest.mark.skipif(platform.system() != 'Windows', reason='See ticket note: fix was only for Windows.') @pytest.mark.version('>=4.0.6') def test_1(act: Action, tmp_sql: Path, capsys): From c6c39c6dc8b5df206a6920657d1e7ad514288a49 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 29 Oct 2024 22:57:01 +0300 Subject: [PATCH 0213/1064] Added/Updated tests\bugs\gh_8230_test.py: Checked on 6.0.0.511-781e5d9 (intermediate build). --- tests/bugs/gh_8230_test.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/bugs/gh_8230_test.py diff --git a/tests/bugs/gh_8230_test.py b/tests/bugs/gh_8230_test.py new file mode 100644 index 00000000..1941c4d3 --- /dev/null +++ b/tests/bugs/gh_8230_test.py @@ -0,0 +1,36 @@ +#coding:utf-8 + +""" +ID: issue-8230 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8230 +TITLE: Ability to obtain PID of server process for current connection without querying mon$ tables +DESCRIPTION: + Test verifies ability to call appropriate rdb$get_context() and compare its value with + mon$attachments.mon$server_pid. They must be equal (and no error must raise). +NOTES: + [29.10.2024] pzotov + Checked on 6.0.0.511-781e5d9 (intermediate build). +""" +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + select cast(rdb$get_context('SYSTEM', 'SERVER_PID') as int) - a.mon$server_pid as result + from mon$attachments a + where a.mon$attachment_id = current_connection; +""" + +act = isql_act('db', test_script, substitutions=[ ('[ \\t]+', ' ') ]) + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + + expected_stdout = f""" + RESULT 0 + """ + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d061161bd135d7ddfd4f4395bea61108dc2c7454 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Oct 2024 10:03:12 +0300 Subject: [PATCH 0214/1064] Added/Updated tests\bugs\gh_8230_test.py: fixed wrong min_version --- tests/bugs/gh_8230_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8230_test.py b/tests/bugs/gh_8230_test.py index 1941c4d3..20901eef 100644 --- a/tests/bugs/gh_8230_test.py +++ b/tests/bugs/gh_8230_test.py @@ -25,7 +25,7 @@ act = isql_act('db', test_script, substitutions=[ ('[ \\t]+', ' ') ]) -@pytest.mark.version('>=4.0.6') +@pytest.mark.version('>=6.0') def test_1(act: Action): expected_stdout = f""" From aa32623dbba3c0c855541d47e95cc6ac19a81493 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Oct 2024 11:43:36 +0300 Subject: [PATCH 0215/1064] Added/Updated tests\bugs\gh_8161_test.py: Splitted expected_out again: added separate block for FB 5.x after discuss with dimitr. --- tests/bugs/gh_8161_test.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py index 3a1d5fa9..92ef9bcb 100644 --- a/tests/bugs/gh_8161_test.py +++ b/tests/bugs/gh_8161_test.py @@ -25,6 +25,9 @@ for RDB$PROCEDURES table (index on columns: RDB$PACKAGE_NAME,RDB$PROCEDURE_NAME - is unique and at least one of these columns allow NULLs). Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds). + + [30.10.2024] pzotov + Splitted expected_out again: added separate block for FB 5.x after discuss with dimitr. """ import zipfile from pathlib import Path @@ -93,19 +96,39 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ................-> Filter ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID ........................-> Bitmap - ............................-> Index "RDB$INDEX_28" Range Scan (full match) + ............................-> Index "RDB$INDEX_nn" Range Scan (full match) ................-> Filter ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID ........................-> Bitmap - ............................-> Index "RDB$INDEX_21" Unique Scan + ............................-> Index "RDB$INDEX_nn" Unique Scan Select Expression ....-> Filter ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID ............-> Bitmap - ................-> Index "RDB$INDEX_3" Range Scan (full match) + ................-> Index "RDB$INDEX_nn" Range Scan (full match) """ expected_stdout_5x = """ + Select Expression + ....-> Singularity Check + ........-> Aggregate + ............-> Nested Loop Join (inner) + ................-> Filter + ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_nn" Range Scan (full match) + ................-> Filter + ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID + ........................-> Bitmap + ............................-> Index "RDB$INDEX_nn" Unique Scan + Select Expression + ....-> Filter + ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID + ............-> Bitmap + ................-> Index "RDB$INDEX_nn" Range Scan (full match) + """ + + expected_stdout_6x = """ Select Expression ....-> Singularity Check ........-> Aggregate @@ -125,6 +148,6 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ................-> Index "RDB$INDEX_nn" Range Scan (full match) """ - act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else 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 From b57a88bd18672e63de6a3be45707819b2317d2d8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Oct 2024 11:48:01 +0300 Subject: [PATCH 0216/1064] Added/Updated tests\functional\arno\optimizer\test_opt_inner_join_05.py: Splitted expected_out : added separate block for FB 5.x after discuss with dimitr. --- .../arno/optimizer/test_opt_inner_join_05.py | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_05.py index 4abba726..31309442 100644 --- a/tests/functional/arno/optimizer/test_opt_inner_join_05.py +++ b/tests/functional/arno/optimizer/test_opt_inner_join_05.py @@ -21,6 +21,9 @@ ("Add key info to the hash join plan output", 23.09.2024 18:26) Discussed with dimitr. Checked on 6.0.0.467-cc183f5, 5.0.2.1513 + + [30.10.2024] pzotov + Splitted expected_out : added separate block for FB 5.x after discuss with dimitr. """ import pytest @@ -326,7 +329,7 @@ #---------------------------------------------------------- -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped @@ -355,31 +358,44 @@ def test_1(act: Action, capsys): expected_stdout_4x = """ Select Expression - ####-> Sort (record length: 150, key length: 44) - ########-> Nested Loop Join (inner) - ############-> Filter - ################-> Table "COUNTRIES" as "C" Access By ID - ####################-> Bitmap - ########################-> Index "I_COUNTRYNAME" Unique Scan - ############-> Filter - ################-> Table "RELATIONS" as "R" Access By ID - ####################-> Bitmap - ########################-> Index "FK_RELATIONS_COUNTRIES" Range Scan (full match) + ....-> Sort (record length: 150, key length: 44) + ........-> Nested Loop Join (inner) + ............-> Filter + ................-> Table "COUNTRIES" as "C" Access By ID + ....................-> Bitmap + ........................-> Index "I_COUNTRYNAME" Unique Scan + ............-> Filter + ................-> Table "RELATIONS" as "R" Access By ID + ....................-> Bitmap + ........................-> Index "FK_RELATIONS_COUNTRIES" Range Scan (full match) """ expected_stdout_5x = """ Select Expression - ####-> Sort (record length: 150, key length: 44) - ########-> Filter - ############-> Hash Join (inner) - ################-> Table "RELATIONS" as "R" Full Scan - ################-> Record Buffer (record length: 81) - ####################-> Filter - ########################-> Table "COUNTRIES" as "C" Access By ID - ############################-> Bitmap - ################################-> Index "I_COUNTRYNAME" Unique Scan + ....-> Sort (record length: 150, key length: 44) + ........-> Filter + ............-> Hash Join (inner) + ................-> Table "RELATIONS" as "R" Full Scan + ................-> Record Buffer (record length: 81) + ....................-> Filter + ........................-> Table "COUNTRIES" as "C" Access By ID + ............................-> Bitmap + ................................-> Index "I_COUNTRYNAME" Range Scan (full match) + """ + + expected_stdout_6x = """ + Select Expression + ....-> Sort (record length: 150, key length: 44) + ........-> Filter + ............-> Hash Join (inner) + ................-> Table "RELATIONS" as "R" Full Scan + ................-> Record Buffer (record length: 81) + ....................-> Filter + ........................-> Table "COUNTRIES" as "C" Access By ID + ............................-> Bitmap + ................................-> Index "I_COUNTRYNAME" Unique Scan """ - act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else 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 From d2c60eef348a9a21ce372a44c676405789b84325 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Oct 2024 15:03:22 +0300 Subject: [PATCH 0217/1064] Added/Updated tests\bugs\core_5464_test.py: Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33793; 3.0.2.32670-0fab1a8. --- tests/bugs/core_5464_test.py | 136 ++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/tests/bugs/core_5464_test.py b/tests/bugs/core_5464_test.py index fa3855c5..4f4593e5 100644 --- a/tests/bugs/core_5464_test.py +++ b/tests/bugs/core_5464_test.py @@ -5,66 +5,106 @@ ISSUE: 5734 TITLE: AV in fbclient when reading blob stored in incompatible encoding DESCRIPTION: + Domain description contains non-ascii text in Latvian + and is created using charset = win1257. + Subsequent connect which tries to get this description uses cp1253 (Greek). + Commit that fixed ticket: 0fab1a85597baa5054a34cae437f5da6096580b0 (20.01.2017 00:43) JIRA: CORE-5464 FBTEST: bugs.core_5464 NOTES: - [06.10.2022] pzotov - Could not complete adjusting for LINUX in new-qa. - DEFERRED. + [30.10.2024] pzotov + Crash *not* occurs but one may note different behaviour of snapshots before and after fix. + + Snapshot before fix (e.g. 90a46fa3, 06-jan-2017) for query to rdb$fields (see view v_domain_descr) + behave differently depending on connection protocol: + * for TCP is does not return any record for query to view 'v_conn_cset'; + * for LOCAL protocol its returns weird 'RDB$SYSTEM_FLAG 18775' and error 'SQLSTATE = 42000 / invalid BLOB ID'. + + Also, error message for query to view 'v_domain_descr' (before fix) was: + Statement failed, SQLSTATE = HY000 + Cannot transliterate character between character sets + request synchronization error + + Discussed with Vlad, letters date: 29-oct-2024. + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33793; 3.0.2.32670-0fab1a8. """ -import platform +import locale +from pathlib import Path + import pytest from firebird.qa import * -init_script = """ - create domain d_int int; - comment on domain d_int is - '*Лев Николаевич Толстой * *Анна Каренина * /Мне отмщение, и аз воздам/ *ЧАСТЬ ПЕРВАЯ* *I * - Все счастливые семьи похожи друг на друга, каждая несчастливая - семья несчастлива по-своему. - Все смешалось в доме Облонских. Жена узнала, что муж был в связи - с бывшею в их доме француженкою-гувернанткой, и объявила мужу, что - не может жить с ним в одном доме. Положение это продолжалось уже - третий день и мучительно чувствовалось и самими супругами, и всеми - членами семьи, и домочадцами. Все члены семьи и домочадцы - чувствовали, что нет смысла в их сожительстве и что на каждом - п1 - '; - commit; -""" +db = db_factory(charset='win1257') +act = isql_act('db', substitutions = [('TCPv(4|6)', 'TCP')]) -db_1 = db_factory(charset='WIN1251', init=init_script) +tmp_sql = temp_file('tmp_core_5464.sql') -test_script = """ - set blob all; - set list on; +@pytest.mark.version('>=3.0.1') +def test_1(act: Action, tmp_sql: Path, capsys): - select c.rdb$character_set_name as connection_cset, r.rdb$character_set_name as db_default_cset - from mon$attachments a - join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id - cross join rdb$database r where a.mon$attachment_id=current_connection; + non_ascii_txt = """ + Oblonsku mājā viss bija sajaukts. + Sieva uzzināja, ka viņas vīram ir attiecības ar franču guvernanti, + kas atradās viņu mājā, un paziņoja vīram, ka nevar dzīvot ar viņu vienā mājā. + """ - select rdb$field_name, rdb$system_flag, rdb$description - from rdb$fields where rdb$description is not null; -""" + init_script = f""" + create domain dm_test int; + comment on domain dm_test is '{non_ascii_txt}'; + commit; + create view v_conn_cset as + select + rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL') as conn_protocol + ,c.rdb$character_set_name as connection_cset + ,r.rdb$character_set_name as db_default_cset + from mon$attachments a + join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + cross join rdb$database r where a.mon$attachment_id=current_connection; -act = isql_act('db_1', test_script) + create view v_domain_descr as + select f.rdb$field_name, f.rdb$system_flag, f.rdb$description + from rdb$database d + left join rdb$fields f on f.rdb$description is not null; + commit; + """ + tmp_sql.write_bytes(init_script.encode('cp1257')) + act.isql(switches=['-q'], input_file = tmp_sql, charset='win1257', combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.return_code == 0 -expected_stdout = """ - CONNECTION_CSET WIN1250 - DB_DEFAULT_CSET WIN1251 -""" + test_sql = f""" + set blob all; + set list on; + set count on; + connect '{act.db.dsn}'; + select v1.* from v_conn_cset as v1; + select v2.* from v_domain_descr as v2; + commit; -expected_stderr = """ - Statement failed, SQLSTATE = 22018 - Cannot transliterate character between character sets -""" + connect '{act.db.db_path}'; + select v3.* from v_conn_cset as v3; + select v4.* from v_domain_descr as v4; + commit; + """ + act.isql(switches=['-q'], connect_db = False, input = test_sql, charset='win1253', combine_output = True, io_enc = locale.getpreferredencoding()) + + act.expected_stdout = """ + CONN_PROTOCOL TCP + CONNECTION_CSET WIN1253 + DB_DEFAULT_CSET WIN1257 + Records affected: 1 + + Statement failed, SQLSTATE = 22018 + Cannot transliterate character between character sets + Records affected: 0 + + + CONN_PROTOCOL + CONNECTION_CSET WIN1253 + DB_DEFAULT_CSET WIN1257 + Records affected: 1 -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3.0.2') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input=test_script, charset='WIN1250') - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + Statement failed, SQLSTATE = 22018 + Cannot transliterate character between character sets + Records affected: 0 + """ + assert act.clean_stdout == act.clean_expected_stdout From 264a8864e91d5f0a8abe26f3874bda7f535300bc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Oct 2024 23:44:28 +0300 Subject: [PATCH 0218/1064] Added/Updated tests\bugs\core_3489_test.py: Re-implemented. See notes. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 --- tests/bugs/core_3489_test.py | 168 +++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 66 deletions(-) diff --git a/tests/bugs/core_3489_test.py b/tests/bugs/core_3489_test.py index f959cf20..48bde78d 100644 --- a/tests/bugs/core_3489_test.py +++ b/tests/bugs/core_3489_test.py @@ -1,66 +1,102 @@ -#coding:utf-8 - -""" -ID: issue-3848 -ISSUE: 3848 -TITLE: Blob transliteration may not happen inside the union -DESCRIPTION: -JIRA: CORE-3489 -FBTEST: bugs.core_3489 -NOTES: - [06.10.2022] pzotov - Could not complete adjusting for LINUX in new-qa. - DEFERRED. -""" -import platform -import pytest -from pathlib import Path -from firebird.qa import * - -init_script = """ - set term ^; - create or alter procedure sp_test - returns ( - msg_blob_id blob sub_type 1 segment size 80 character set unicode_fss) - AS - begin - msg_blob_id= 'Это проверка на вывод строки "Йцукёнг"'; -- text in cyrillic - suspend; - end - ^ - set term ;^ - commit; -""" - -db = db_factory(charset='WIN1251', init=init_script) - -act = python_act('db', substitutions=[('MSG_BLOB_ID.*', '')]) - -expected_stdout = """ - Это проверка на вывод строки "Йцукёнг" - Это проверка на вывод строки "Йцукёнг" - Records affected: 2 -""" - -script_file = temp_file('test_script.sql') - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3') -def test_1(act: Action, script_file: Path): - script_file.write_text(""" - set list on; - set blob all; - set count on; - set list on; - - select msg_blob_id - from sp_test - union - select msg_blob_id - from sp_test; - """, encoding='cp1251') - act.expected_stdout = expected_stdout - act.isql(switches=[], input_file=script_file, charset='WIN1251') - assert act.clean_stdout == act.clean_expected_stdout - - +#coding:utf-8 + +""" +ID: issue-3848 +ISSUE: 3848 +TITLE: Blob transliteration may not happen inside the union +DESCRIPTION: +JIRA: CORE-3489 +FBTEST: bugs.core_3489 +NOTES: + [30.10.2024] pzotov + Bug was fixed for too old FB (3.0 Alpha 1), firebird-driver and/or QA-plugin will not able to run on this version. + to check this version in order to reproduce problem. + Source for this test was taken from ticket almost w/o changes. Only aux view has been added ('v_conn_cset') for + showing current connection protocol and character set - we make query to this view two twice: one for TCP and then + for local protocol. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 +""" + +import locale +from pathlib import Path +import pytest +from firebird.qa import * + +db = db_factory(charset='WIN1251') + +act = python_act('db', substitutions=[('MSG_BLOB_ID.*', ''), ('TCPv(4|6)', 'TCP')]) + +expected_stdout = """ + CONN_PROTOCOL TCP + CONNECTION_CSET WIN1251 + DB_DEFAULT_CSET WIN1251 + Records affected: 1 + Это проверка на вывод строки "Йцукёнг" + Это проверка на вывод строки "Йцукёнг" + Records affected: 2 + + CONN_PROTOCOL + CONNECTION_CSET WIN1251 + DB_DEFAULT_CSET WIN1251 + Records affected: 1 + Это проверка на вывод строки "Йцукёнг" + Это проверка на вывод строки "Йцукёнг" + Records affected: 2 +""" + +tmp_sql = temp_file('tmp_core_3489.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + tmp_sql.write_text( + f""" + set bail on; + set list on; + set blob all; + set count on; + set names win1251; + connect '{act.db.dsn}'; + create view v_conn_cset as + select + rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL') as conn_protocol + ,c.rdb$character_set_name as connection_cset + ,r.rdb$character_set_name as db_default_cset + from mon$attachments a + join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + cross join rdb$database r where a.mon$attachment_id=current_connection; + + set term ^; + create or alter procedure sp_test + returns ( + msg_blob_id blob sub_type 1 segment size 80 character set unicode_fss) + AS + begin + msg_blob_id= 'Это проверка на вывод строки "Йцукёнг"'; -- text in cyrillic + suspend; + end + ^ + set term ;^ + commit; + -------------------------- + connect '{act.db.dsn}'; -- check TCP protocol + select * from v_conn_cset; + select msg_blob_id + from sp_test + union + select msg_blob_id + from sp_test; + commit; + -------------------------- + connect '{act.db.db_path}'; -- check local protocol + select * from v_conn_cset; + select msg_blob_id + from sp_test + union + select msg_blob_id + from sp_test; + """ + ,encoding='cp1251') + act.expected_stdout = expected_stdout + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'WIN1251', combine_output = True, connect_db = False) + assert act.clean_stdout == act.clean_expected_stdout From f26daf2d0168e85901eae7437e6e672589f17e96 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 00:15:48 +0300 Subject: [PATCH 0219/1064] Added/Updated tests\bugs\core_2227_test.py: Re-implemented. See notes. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 --- tests/bugs/core_2227_test.py | 133 +++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 51 deletions(-) diff --git a/tests/bugs/core_2227_test.py b/tests/bugs/core_2227_test.py index 817dfc74..816b0853 100644 --- a/tests/bugs/core_2227_test.py +++ b/tests/bugs/core_2227_test.py @@ -1,51 +1,82 @@ -#coding:utf-8 - -""" -ID: issue-2655 -ISSUE: 2655 -TITLE: Problem with column names with Accents and triggers -DESCRIPTION: -JIRA: CORE-2227 -FBTEST: bugs.core_2227 -NOTES: - [25.1.2022] pcisar - For yet unknown reason, ISQL gets malformed stdin from act.execute() although it was passed - correctly encoded in iso8859_1. Test changed to use script file writen in iso8859_1 - which works fine. - [06.10.2022] pzotov - Could not complete adjusting for LINUX in new-qa. - DEFERRED. -""" -import platform -import pytest -from pathlib import Path -from firebird.qa import * - -init_script = """ - RECREATE TABLE TESTING ( - "CÓDIGO" INTEGER - ); -""" - -db = db_factory(charset='ISO8859_1', init=init_script) - -test_script = """ - SET TERM ^; - CREATE TRIGGER TESTING_I FOR TESTING - ACTIVE BEFORE INSERT POSITION 0 - AS - BEGIN - NEW."CÓDIGO" = 1; - END - ^ -""" - -act = isql_act('db', test_script) - -script_file = temp_file('test_script.sql') - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3') -def test_1(act: Action, script_file: Path): - script_file.write_text(test_script, encoding='iso8859_1') - act.isql(switches=[], input_file=script_file) +#coding:utf-8 + +""" +ID: issue-2655 +ISSUE: 2655 +TITLE: Problem with column names with Accents and triggers +DESCRIPTION: +JIRA: CORE-2227 +FBTEST: bugs.core_2227 +NOTES: + [31.10.2024] pzotov + Bug was fixed for too old FB (2.1.2; 2.5 Beta1) so firebird-driver and/or QA-plugin + will not able to run on this version in order to reproduce problem. + Source for this test was taken from ticket almost w/o changes. Only aux view has been added ('v_conn_cset') for + showing current connection protocol and character set - we make query to this view two twice: one for TCP and then + for local protocol. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 +""" +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='ISO8859_1') + +act = isql_act('db', substitutions = [ ('[ \\t]+', ' '), ('TCPv(4|6)', 'TCP') ]) + +tmp_sql = temp_file('tmp_core_2227.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + test_script = f""" + set bail on; + set list on; + recreate table testing ( + "CÓDIGO" integer + ); + commit; + set term ^; + create trigger testing_i for testing active before insert position 0 as + begin + new."CÓDIGO" = 1; + end + ^ + set term ;^ + commit; + + create view v_conn_cset as + select + rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL') as conn_protocol + ,c.rdb$character_set_name as connection_cset + ,r.rdb$character_set_name as db_default_cset + from mon$attachments a + join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + cross join rdb$database r where a.mon$attachment_id=current_connection; + commit; + + connect '{act.db.dsn}'; + select * from v_conn_cset; + insert into testing default values returning "CÓDIGO"; + rollback; + + connect '{act.db.db_path}'; + select * from v_conn_cset; + insert into testing default values returning "CÓDIGO"; + """ + + tmp_sql.write_text(test_script, encoding='iso8859_1') + act.expected_stdout = """ + CONN_PROTOCOL TCPv4 + CONNECTION_CSET ISO8859_1 + DB_DEFAULT_CSET ISO8859_1 + CÓDIGO 1 + + CONN_PROTOCOL + CONNECTION_CSET ISO8859_1 + DB_DEFAULT_CSET ISO8859_1 + CÓDIGO 1 + """ + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'iso8859_1', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From b64fc14d0ec54e616aba2bdea0133e7234d6d491 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 00:16:41 +0300 Subject: [PATCH 0220/1064] Added/Updated tests\bugs\core_3489_test.py: minor change: adjusted notes. --- tests/bugs/core_3489_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3489_test.py b/tests/bugs/core_3489_test.py index 48bde78d..db620ff4 100644 --- a/tests/bugs/core_3489_test.py +++ b/tests/bugs/core_3489_test.py @@ -9,8 +9,8 @@ FBTEST: bugs.core_3489 NOTES: [30.10.2024] pzotov - Bug was fixed for too old FB (3.0 Alpha 1), firebird-driver and/or QA-plugin will not able to run on this version. - to check this version in order to reproduce problem. + Bug was fixed for too old FB (3.0 Alpha 1), firebird-driver and/or QA-plugin + will not able to run on this version in order to reproduce problem. Source for this test was taken from ticket almost w/o changes. Only aux view has been added ('v_conn_cset') for showing current connection protocol and character set - we make query to this view two twice: one for TCP and then for local protocol. From ba89f2888e6a741e242dda277b6fae436df754fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 00:54:53 +0300 Subject: [PATCH 0221/1064] Added/Updated tests\bugs\core_1366_test.py: Re-implemented. See notes. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 --- tests/bugs/core_1366_test.py | 231 +++++++++++++++++------------------ 1 file changed, 114 insertions(+), 117 deletions(-) diff --git a/tests/bugs/core_1366_test.py b/tests/bugs/core_1366_test.py index c3788cb8..1d53680d 100644 --- a/tests/bugs/core_1366_test.py +++ b/tests/bugs/core_1366_test.py @@ -1,117 +1,114 @@ -#coding:utf-8 - -""" -ID: issue-1784 -ISSUE: 1784 -TITLE: French insensitive collation FR_FR_CI_AI -DESCRIPTION: -JIRA: CORE-1366 -FBTEST: bugs.core_1366 -NOTES: - [06.10.2022] pzotov - Could not complete adjusting for LINUX in new-qa. - DEFERRED. -""" -import platform -import pytest -from firebird.qa import * - -init_script = """ - recreate table test(id int); - commit; - - set term ^; - execute block as - begin - begin execute statement 'drop collation coll_fr'; when any do begin end end - end - ^set term ;^ - commit; - - create collation coll_fr for iso8859_1 from external ('FR_FR') case insensitive accent insensitive; - commit; - - recreate table test(id int, cf varchar(10) collate coll_fr); - commit; - - recreate table noac(id int, nf varchar(10) collate coll_fr); - commit; - - -- http://french.about.com/od/pronunciation/a/accents.htm - - -- ### ONCE AGAIN ### - -- 1) for checking this under ISQL following must be encoded in ISO8859_1 - -- 2) for running under fbt_run utility following must be encoded in UTF8. - - -- (cedilla) is found only on the letter "C": - insert into test(id, cf) values( 1010, 'ç'); - - -- (acute accent) can only be on an "E" - insert into test(id, cf) values( 1020, 'é'); - - -- (grave accent) can be found on an "A", "E", "U" - insert into test(id, cf) values( 1030, 'à'); - insert into test(id, cf) values( 1040, 'è'); - insert into test(id, cf) values( 1050, 'ù'); - - -- (dieresis or umlaut) can be on an E, I and U - insert into test(id, cf) values( 1060, 'ë'); - insert into test(id, cf) values( 1070, 'ï'); - insert into test(id, cf) values( 1080, 'ü'); - - -- (circumflex) can be on an A, E, I, O and U - insert into test(id, cf) values( 1090, 'â'); - insert into test(id, cf) values( 1110, 'ê'); - insert into test(id, cf) values( 1120, 'î'); - insert into test(id, cf) values( 1130, 'û'); - insert into test(id, cf) values( 1140, 'ô'); - commit; - - -- ANSI letters that should be equal to diacritical - -- when doing comparison CI_AI: - insert into noac(id, nf) values( 1150, 'A'); - insert into noac(id, nf) values( 1160, 'C'); - insert into noac(id, nf) values( 1170, 'E'); - insert into noac(id, nf) values( 1180, 'I'); - insert into noac(id, nf) values( 1190, 'O'); - insert into noac(id, nf) values( 1200, 'U'); - commit; - -""" - -db = db_factory(charset='ISO8859_1', init=init_script) - -test_script = """ - select n.id n_id, n.nf, t.cf, t.id t_id - from noac n - left join test t on n.nf is not distinct from t.cf - order by n_id, t_id; -""" - -act = isql_act('db', test_script, substitutions=[('=.*', ''), ('[ \t]+', ' ')]) - -expected_stdout = """ - N_ID NF CF T_ID - ============ ========== ========== ============ - 1150 A à 1030 - 1150 A â 1090 - 1160 C ç 1010 - 1170 E é 1020 - 1170 E è 1040 - 1170 E ë 1060 - 1170 E ê 1110 - 1180 I ï 1070 - 1180 I î 1120 - 1190 O ô 1140 - 1200 U ù 1050 - 1200 U ü 1080 - 1200 U û 1130 -""" - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - +#coding:utf-8 + +""" +ID: issue-1784 +ISSUE: 1784 +TITLE: French insensitive collation FR_FR_CI_AI +DESCRIPTION: Add French case-/accent-insensitive collation. +JIRA: CORE-1366 +FBTEST: bugs.core_1366 +NOTES: + [31.10.2024] pzotov + Bug was fixed for too old FB (2.1.8), firebird-driver and/or QA-plugin + will not able to run on this version in order to reproduce problem. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 +""" +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='ISO8859_1') +act = isql_act('db', substitutions=[('=.*', ''), ('[ \\t]+', ' ')]) +tmp_sql = temp_file('tmp_core_1366.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + + test_script = f""" + recreate table test(id int); + commit; + + set term ^; + execute block as + begin + begin execute statement 'drop collation coll_fr'; when any do begin end end + end + ^set term ;^ + commit; + + create collation coll_fr for iso8859_1 from external ('FR_FR') case insensitive accent insensitive; + commit; + + recreate table test(id int, cf varchar(10) collate coll_fr); + commit; + + recreate table noac(id int, nf varchar(10) collate coll_fr); + commit; + + -- http://french.about.com/od/pronunciation/a/accents.htm + + -- (cedilla) is found only on the letter "C": + insert into test(id, cf) values( 1010, 'ç'); + + -- (acute accent) can only be on an "E" + insert into test(id, cf) values( 1020, 'é'); + + -- (grave accent) can be found on an "A", "E", "U" + insert into test(id, cf) values( 1030, 'à'); + insert into test(id, cf) values( 1040, 'è'); + insert into test(id, cf) values( 1050, 'ù'); + + -- (dieresis or umlaut) can be on an E, I and U + insert into test(id, cf) values( 1060, 'ë'); + insert into test(id, cf) values( 1070, 'ï'); + insert into test(id, cf) values( 1080, 'ü'); + + -- (circumflex) can be on an A, E, I, O and U + insert into test(id, cf) values( 1090, 'â'); + insert into test(id, cf) values( 1110, 'ê'); + insert into test(id, cf) values( 1120, 'î'); + insert into test(id, cf) values( 1130, 'û'); + insert into test(id, cf) values( 1140, 'ô'); + commit; + + -- ANSI letters that should be equal to diacritical + -- when doing comparison CI_AI: + insert into noac(id, nf) values( 1150, 'A'); + insert into noac(id, nf) values( 1160, 'C'); + insert into noac(id, nf) values( 1170, 'E'); + insert into noac(id, nf) values( 1180, 'I'); + insert into noac(id, nf) values( 1190, 'O'); + insert into noac(id, nf) values( 1200, 'U'); + commit; + select n.id n_id, n.nf, t.cf, t.id t_id + from noac n + left join test t on n.nf is not distinct from t.cf + order by n_id, t_id; + """ + + # https://github.com/FirebirdSQL/firebird/issues/1784#issuecomment-826188088 + # ::: NB ::: + # For proper output of test, input script must be encoded in ISO8859_1 rather than in UTF-8. + # + tmp_sql.write_text(test_script, encoding='iso8859_1') + act.expected_stdout = """ + N_ID NF CF T_ID + ============ ========== ========== ============ + 1150 A à 1030 + 1150 A â 1090 + 1160 C ç 1010 + 1170 E é 1020 + 1170 E è 1040 + 1170 E ë 1060 + 1170 E ê 1110 + 1180 I ï 1070 + 1180 I î 1120 + 1190 O ô 1140 + 1200 U ù 1050 + 1200 U ü 1080 + 1200 U û 1130 + """ + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'iso8859_1', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 86b78aa07eb4f8ac442a3e610e915551696e6b1e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 01:04:04 +0300 Subject: [PATCH 0222/1064] Added/Updated tests\bugs\core_0857_test.py: Re-implemented. See notes. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 --- tests/bugs/core_0857_test.py | 153 ++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/tests/bugs/core_0857_test.py b/tests/bugs/core_0857_test.py index 0b8ae763..a9938d86 100644 --- a/tests/bugs/core_0857_test.py +++ b/tests/bugs/core_0857_test.py @@ -1,76 +1,77 @@ -#coding:utf-8 - -""" -ID: issue-1247 -ISSUE: 1247 -TITLE: Containing not working correctly -DESCRIPTION: -JIRA: CORE-857 -FBTEST: bugs.core_0857 -NOTES: - [06.10.2022] pzotov - Could not complete adjusting for LINUX in new-qa. - DEFERRED. - -""" - -import platform -import pytest -from firebird.qa import * - -init_script = """ -set echo on; -set bail on; - create collation test_coll_ci_ai for win1252 from WIN_PTBR - case insensitive - accent insensitive - ; - - create table test ( - id int, - f01 varchar(100), - f02 varchar(100) collate WIN_PTBR - ); - - insert into test(id, f01) values(1, 'IHF|groß|850xC|P1'); - update test set f02=f01; - commit; - create view v_test as - select octet_length(t.f01) - octet_length(replace(t.f01, 'ß', '')) as "octet_length diff:" from test t; -""" - -db = db_factory(charset='WIN1252', init=init_script) - -expected_stdout = """ - CONNECTION_CSET WIN1252 - test_1 result: - test_2 result: 1 - ci_ai result: 1 - between result: 1 - octet_length diff: 1 -""" - -test_script = """ - set list on; - select c.rdb$character_set_name as connection_cset - from mon$attachments a - join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id - where a.mon$attachment_id = current_connection; - - select t.id as "test_1 result:" from rdb$database r left join test t on t.f01 not containing 'P1' and t.f01 like 'IHF|gro_|850_C|P1'; - select t.id as "test_2 result:" from rdb$database r left join test t on t.f01 containing 'P1' and t.f01 like 'IHF|gro_|850_C|P1'; - select t.id as "ci_ai result:" from rdb$database r left join test t on lower(t.f02) = upper(t.f02); - select t.id as "between result:" from rdb$database r left join test t on lower(t.f01) between lower(t.f02) and upper(t.f02); - select * from v_test; -""" - -act = isql_act('db', test_script) - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - - +#coding:utf-8 + +""" +ID: issue-1247 +ISSUE: 1247 +TITLE: Containing not working correctly +DESCRIPTION: +JIRA: CORE-857 +FBTEST: bugs.core_0857 +NOTES: + [31.10.2024] pzotov + Bug was fixed for too old FB (2.0 RC4 / 2.1 ALpha 1), firebird-driver and/or QA-plugin + will not able to run on this version in order to reproduce problem. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 +""" +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='WIN1252') +act = isql_act('db', substitutions=[('[ \\t]+', ' ')]) +tmp_sql = temp_file('tmp_core_0857.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + + test_script = """ + set bail on; + create collation test_coll_ci_ai for win1252 from WIN_PTBR + case insensitive + accent insensitive + ; + + create table test ( + id int, + f01 varchar(100), + f02 varchar(100) collate WIN_PTBR + ); + + insert into test(id, f01) values(1, 'IHF|groß|850xC|P1'); + update test set f02=f01; + commit; + create view v_test as + select octet_length(t.f01) - octet_length(replace(t.f01, 'ß', '')) as "octet_length diff:" from test t; + commit; + + set list on; + select c.rdb$character_set_name as connection_cset + from mon$attachments a + join rdb$character_sets c on a.mon$character_set_id = c.rdb$character_set_id + where a.mon$attachment_id = current_connection; + + select t.id as "test_1 result:" from rdb$database r left join test t on t.f01 not containing 'P1' and t.f01 like 'IHF|gro_|850_C|P1'; + select t.id as "test_2 result:" from rdb$database r left join test t on t.f01 containing 'P1' and t.f01 like 'IHF|gro_|850_C|P1'; + select t.id as "ci_ai result:" from rdb$database r left join test t on lower(t.f02) = upper(t.f02); + select t.id as "between result:" from rdb$database r left join test t on lower(t.f01) between lower(t.f02) and upper(t.f02); + select * from v_test; + """ + + # ::: NB ::: + # For proper output of test, input script must be encoded in cp1252 rather than in UTF-8. + # + tmp_sql.write_text(test_script, encoding = 'cp1252') + + act.expected_stdout = """ + CONNECTION_CSET WIN1252 + test_1 result: + test_2 result: 1 + ci_ai result: 1 + between result: 1 + octet_length diff: 1 + """ + + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'win1252', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 90951ffe146bf4c78d99894e88eba4fae8275a81 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 01:17:54 +0300 Subject: [PATCH 0223/1064] Added pytest.mark.intl to have ability filtering these files if only QA-run related to non-ascii data is needed. --- tests/bugs/core_0857_test.py | 3 ++- tests/bugs/core_1366_test.py | 1 + tests/bugs/core_2227_test.py | 1 + tests/bugs/core_3489_test.py | 1 + tests/bugs/core_5464_test.py | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0857_test.py b/tests/bugs/core_0857_test.py index a9938d86..47506058 100644 --- a/tests/bugs/core_0857_test.py +++ b/tests/bugs/core_0857_test.py @@ -9,7 +9,7 @@ FBTEST: bugs.core_0857 NOTES: [31.10.2024] pzotov - Bug was fixed for too old FB (2.0 RC4 / 2.1 ALpha 1), firebird-driver and/or QA-plugin + Bug was fixed for too old FB (2.0 RC4 / 2.1 Alpha 1), firebird-driver and/or QA-plugin will not able to run on this version in order to reproduce problem. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.2.32670, 3,0,1,32609 @@ -23,6 +23,7 @@ act = isql_act('db', substitutions=[('[ \\t]+', ' ')]) tmp_sql = temp_file('tmp_core_0857.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.0') def test_1(act: Action, tmp_sql: Path): diff --git a/tests/bugs/core_1366_test.py b/tests/bugs/core_1366_test.py index 1d53680d..7fa1c8d8 100644 --- a/tests/bugs/core_1366_test.py +++ b/tests/bugs/core_1366_test.py @@ -23,6 +23,7 @@ act = isql_act('db', substitutions=[('=.*', ''), ('[ \\t]+', ' ')]) tmp_sql = temp_file('tmp_core_1366.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.0') def test_1(act: Action, tmp_sql: Path): diff --git a/tests/bugs/core_2227_test.py b/tests/bugs/core_2227_test.py index 816b0853..da9e1b03 100644 --- a/tests/bugs/core_2227_test.py +++ b/tests/bugs/core_2227_test.py @@ -28,6 +28,7 @@ tmp_sql = temp_file('tmp_core_2227.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.0') def test_1(act: Action, tmp_sql: Path): test_script = f""" diff --git a/tests/bugs/core_3489_test.py b/tests/bugs/core_3489_test.py index db620ff4..7cd10edf 100644 --- a/tests/bugs/core_3489_test.py +++ b/tests/bugs/core_3489_test.py @@ -47,6 +47,7 @@ tmp_sql = temp_file('tmp_core_3489.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.0') def test_1(act: Action, tmp_sql: Path): tmp_sql.write_text( diff --git a/tests/bugs/core_5464_test.py b/tests/bugs/core_5464_test.py index 4f4593e5..8949a8c3 100644 --- a/tests/bugs/core_5464_test.py +++ b/tests/bugs/core_5464_test.py @@ -39,6 +39,7 @@ tmp_sql = temp_file('tmp_core_5464.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.1') def test_1(act: Action, tmp_sql: Path, capsys): From 26eae15c96b72d760144cb926f5f395d83def5b0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 11:16:22 +0300 Subject: [PATCH 0224/1064] Added/Updated tests\bugs\gh_8161_test.py: Adjusted expected_out discuss with dimitr (explained plans for FB 3.x ...6.x now are identical). --- tests/bugs/gh_8161_test.py | 55 ++++---------------------------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py index 92ef9bcb..28e5292f 100644 --- a/tests/bugs/gh_8161_test.py +++ b/tests/bugs/gh_8161_test.py @@ -20,14 +20,9 @@ Confirmed bug (regression) on 3.0.12.33735 (date of build: 09-mar-2024). Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374. - [25.10.2024] pzotov - Splitted expected_out after fixed #8290: 'Index "RDB$INDEX_nn" Range Scan (full match)' must appear in explained plan) - for RDB$PROCEDURES table (index on columns: RDB$PACKAGE_NAME,RDB$PROCEDURE_NAME - is unique and at least one of these - columns allow NULLs). - Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds). - - [30.10.2024] pzotov - Splitted expected_out again: added separate block for FB 5.x after discuss with dimitr. + [31.10.2024] pzotov + Adjusted expected_out discuss with dimitr (explained plans for FB 3.x ...6.x now are identical). + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1551, 6.0.0.515 """ import zipfile from pathlib import Path @@ -88,27 +83,7 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ps = cur.prepare(test_sql) print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - expected_stdout_4x = """ - Select Expression - ....-> Singularity Check - ........-> Aggregate - ............-> Nested Loop Join (inner) - ................-> Filter - ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID - ........................-> Bitmap - ............................-> Index "RDB$INDEX_nn" Range Scan (full match) - ................-> Filter - ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID - ........................-> Bitmap - ............................-> Index "RDB$INDEX_nn" Unique Scan - Select Expression - ....-> Filter - ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID - ............-> Bitmap - ................-> Index "RDB$INDEX_nn" Range Scan (full match) - """ - - expected_stdout_5x = """ + expected_stdout = """ Select Expression ....-> Singularity Check ........-> Aggregate @@ -127,27 +102,7 @@ def test_1(act: Action, tmp_fbk: Path, capsys): ............-> Bitmap ................-> Index "RDB$INDEX_nn" Range Scan (full match) """ - - expected_stdout_6x = """ - Select Expression - ....-> Singularity Check - ........-> Aggregate - ............-> Nested Loop Join (inner) - ................-> Filter - ....................-> Table "RDB$DEPENDENCIES" as "DEP" Access By ID - ........................-> Bitmap - ............................-> Index "RDB$INDEX_nn" Range Scan (full match) - ................-> Filter - ....................-> Table "RDB$PROCEDURES" as "PRC" Access By ID - ........................-> Bitmap - ............................-> Index "RDB$INDEX_nn" Range Scan (full match) - Select Expression - ....-> Filter - ........-> Table "RDB$RELATION_FIELDS" as "X" Access By ID - ............-> Bitmap - ................-> Index "RDB$INDEX_nn" Range Scan (full match) - """ - act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From a8d5d389f724006125e3341e0265aa45020db014 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 11:19:40 +0300 Subject: [PATCH 0225/1064] Added/Updated tests\functional\arno\optimizer\test_opt_inner_join_05.py: Adjusted expected_out discuss with dimitr. Explained plans for 5.x and 6.x are now identical. Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1551, 6.0.0.515 --- .../arno/optimizer/test_opt_inner_join_05.py | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_05.py index 31309442..35cbbba6 100644 --- a/tests/functional/arno/optimizer/test_opt_inner_join_05.py +++ b/tests/functional/arno/optimizer/test_opt_inner_join_05.py @@ -22,8 +22,9 @@ Discussed with dimitr. Checked on 6.0.0.467-cc183f5, 5.0.2.1513 - [30.10.2024] pzotov - Splitted expected_out : added separate block for FB 5.x after discuss with dimitr. + [31.10.2024] pzotov + Adjusted expected_out discuss with dimitr. Explained plans for 5.x and 6.x are now identical. + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1551, 6.0.0.515 """ import pytest @@ -383,19 +384,6 @@ def test_1(act: Action, capsys): ................................-> Index "I_COUNTRYNAME" Range Scan (full match) """ - expected_stdout_6x = """ - Select Expression - ....-> Sort (record length: 150, key length: 44) - ........-> Filter - ............-> Hash Join (inner) - ................-> Table "RELATIONS" as "R" Full Scan - ................-> Record Buffer (record length: 81) - ....................-> Filter - ........................-> Table "COUNTRIES" as "C" Access By ID - ............................-> Bitmap - ................................-> Index "I_COUNTRYNAME" Unique Scan - """ - - act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 19c51597e58412971b94b6cae9f1894cac190170 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 11:28:06 +0300 Subject: [PATCH 0226/1064] Added pytest.mark.intl to have ability filtering these files if only QA-run related to non-ascii data is needed. --- tests/functional/exception/test_handling_name_and_message.py | 1 + tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/functional/exception/test_handling_name_and_message.py b/tests/functional/exception/test_handling_name_and_message.py index e737cb9d..c3e3ace3 100644 --- a/tests/functional/exception/test_handling_name_and_message.py +++ b/tests/functional/exception/test_handling_name_and_message.py @@ -157,6 +157,7 @@ Records affected: 1 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py b/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py index 42f46800..45ad345b 100644 --- a/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py +++ b/tests/functional/intl/test_non_ascii_firebird_and_trace_utf8.py @@ -41,6 +41,7 @@ act = python_act('db', substitutions = substitutions) +@pytest.mark.intl @pytest.mark.trace @pytest.mark.version('>=4.0') def test_1(act: Action, tmp_worker: User, capsys): From 0dece2247fddefdc3c5833a2b8e6666be1d9ff47 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 13:17:14 +0300 Subject: [PATCH 0227/1064] Added pytest.mark.intl to have ability filtering these files if only QA-run related to non-ascii data is needed. --- tests/bugs/core_0986_test.py | 1 + tests/bugs/core_1026_utf8_test.py | 1 + tests/bugs/core_1254_test.py | 1 + tests/bugs/core_1331_test.py | 1 + tests/bugs/core_2606_test.py | 1 + tests/bugs/core_2912_test.py | 1 + tests/bugs/core_3401_test.py | 1 + tests/bugs/core_3416_test.py | 1 + tests/bugs/core_3511_test.py | 1 + tests/bugs/core_4160_test.py | 1 + tests/bugs/core_4301_test.py | 1 + tests/bugs/core_4599_test.py | 1 + tests/bugs/core_4743_test.py | 1 + tests/bugs/core_4760_test.py | 1 + tests/bugs/core_4881_test.py | 1 + tests/bugs/core_5220_test.py | 1 + tests/bugs/core_5389_test.py | 1 + tests/bugs/core_5470_addi_test.py | 1 + tests/bugs/core_5480_test.py | 1 + tests/bugs/core_5695_test.py | 1 + tests/bugs/core_5926_test.py | 1 + tests/bugs/core_6166_test.py | 1 + tests/bugs/core_6211_test.py | 1 + tests/bugs/gh_0731_test.py | 1 + tests/bugs/gh_7045_test.py | 1 + tests/bugs/gh_8015_test.py | 1 + 26 files changed, 26 insertions(+) diff --git a/tests/bugs/core_0986_test.py b/tests/bugs/core_0986_test.py index 5aed18ef..da60b44f 100644 --- a/tests/bugs/core_0986_test.py +++ b/tests/bugs/core_0986_test.py @@ -188,6 +188,7 @@ tmp_file = temp_file('tmp_0986_non_ascii_ddl.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_file: Path): tmp_file.write_bytes(non_ascii_ddl.encode('cp1251')) diff --git a/tests/bugs/core_1026_utf8_test.py b/tests/bugs/core_1026_utf8_test.py index 3710434b..15e8bb07 100644 --- a/tests/bugs/core_1026_utf8_test.py +++ b/tests/bugs/core_1026_utf8_test.py @@ -261,6 +261,7 @@ Records affected: 30 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_1254_test.py b/tests/bugs/core_1254_test.py index 06533df9..651e52ed 100644 --- a/tests/bugs/core_1254_test.py +++ b/tests/bugs/core_1254_test.py @@ -101,6 +101,7 @@ case_SENSITIVE_distinct_gr_4 1 """ +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_1331_test.py b/tests/bugs/core_1331_test.py index fe9b6f3b..edc993b8 100644 --- a/tests/bugs/core_1331_test.py +++ b/tests/bugs/core_1331_test.py @@ -48,6 +48,7 @@ EXECUTE_STTM_SELECT милан """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_2606_test.py b/tests/bugs/core_2606_test.py index a85ab1f4..6b0dc212 100644 --- a/tests/bugs/core_2606_test.py +++ b/tests/bugs/core_2606_test.py @@ -50,6 +50,7 @@ VARC1_ASCII A. """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.script = test_script diff --git a/tests/bugs/core_2912_test.py b/tests/bugs/core_2912_test.py index 47b96410..2c6c1d61 100644 --- a/tests/bugs/core_2912_test.py +++ b/tests/bugs/core_2912_test.py @@ -74,6 +74,7 @@ CU FAÿ """ +@pytest.mark.intl @pytest.mark.platform('Windows') @pytest.mark.version('>=3') def test_1(act: Action): diff --git a/tests/bugs/core_3401_test.py b/tests/bugs/core_3401_test.py index 5d369048..dbadd0de 100644 --- a/tests/bugs/core_3401_test.py +++ b/tests/bugs/core_3401_test.py @@ -164,6 +164,7 @@ EQUAL 1 """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3416_test.py b/tests/bugs/core_3416_test.py index 2a172095..9e315357 100644 --- a/tests/bugs/core_3416_test.py +++ b/tests/bugs/core_3416_test.py @@ -48,6 +48,7 @@ script_file = temp_file('test_script.sql') +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action, script_file: Path): script_file.write_text(""" diff --git a/tests/bugs/core_3511_test.py b/tests/bugs/core_3511_test.py index 3dba7c29..8b4457cb 100644 --- a/tests/bugs/core_3511_test.py +++ b/tests/bugs/core_3511_test.py @@ -37,6 +37,7 @@ act = python_act('db') +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User, tmp_role1: Role, tmp_role2: Role, capsys): init_script = f""" diff --git a/tests/bugs/core_4160_test.py b/tests/bugs/core_4160_test.py index 4014b728..3397af2e 100644 --- a/tests/bugs/core_4160_test.py +++ b/tests/bugs/core_4160_test.py @@ -83,6 +83,7 @@ - Russian: Новый остаток будет меньше нуля (-6) """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stderr = expected_stderr diff --git a/tests/bugs/core_4301_test.py b/tests/bugs/core_4301_test.py index fb5c45a7..aaff92c2 100644 --- a/tests/bugs/core_4301_test.py +++ b/tests/bugs/core_4301_test.py @@ -62,6 +62,7 @@ é alguém do Brasil """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action, user_a: User, user_b: User): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4599_test.py b/tests/bugs/core_4599_test.py index 71759594..377b7569 100644 --- a/tests/bugs/core_4599_test.py +++ b/tests/bugs/core_4599_test.py @@ -835,6 +835,7 @@ OVERLAY_UTF8_TO_ASCII_LO 1 """ +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4743_test.py b/tests/bugs/core_4743_test.py index 6c28ed6d..995a5d69 100644 --- a/tests/bugs/core_4743_test.py +++ b/tests/bugs/core_4743_test.py @@ -167,6 +167,7 @@ privilege:exec : YES """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action, non_acii_user: User, test_role: Role, capsys): act.isql(switches=['-b', '-q'], input=ddl_script) diff --git a/tests/bugs/core_4760_test.py b/tests/bugs/core_4760_test.py index e4d2b18f..ee633b84 100644 --- a/tests/bugs/core_4760_test.py +++ b/tests/bugs/core_4760_test.py @@ -39,6 +39,7 @@ WHOAMI : {NON_ASCII_NAME} """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action, non_ascii_user: User, capsys): with act.db.connect(user=non_ascii_user.name, password=non_ascii_user.password) as con: diff --git a/tests/bugs/core_4881_test.py b/tests/bugs/core_4881_test.py index 5d8d4c1c..e9c78ece 100644 --- a/tests/bugs/core_4881_test.py +++ b/tests/bugs/core_4881_test.py @@ -34,6 +34,7 @@ C_LEN_UTF8_MIXED 16383 """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): script_file = Path(act.files_dir / 'core_4881.zip', at='core_4881_script.sql') diff --git a/tests/bugs/core_5220_test.py b/tests/bugs/core_5220_test.py index 48374cd9..e7dc216f 100644 --- a/tests/bugs/core_5220_test.py +++ b/tests/bugs/core_5220_test.py @@ -62,6 +62,7 @@ r.rdb$system_flag is distinct from 1; """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): # diff --git a/tests/bugs/core_5389_test.py b/tests/bugs/core_5389_test.py index 8f9a1b8e..aab83154 100644 --- a/tests/bugs/core_5389_test.py +++ b/tests/bugs/core_5389_test.py @@ -45,6 +45,7 @@ script_file = temp_file('test-script.sql') +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action, script_file: Path): script_file.write_text(test_script, encoding='cp1251') diff --git a/tests/bugs/core_5470_addi_test.py b/tests/bugs/core_5470_addi_test.py index 78a4568c..e46686f2 100644 --- a/tests/bugs/core_5470_addi_test.py +++ b/tests/bugs/core_5470_addi_test.py @@ -77,6 +77,7 @@ expected_stdout_trace = test_sql.replace('set list on;', '').replace(';','') +@pytest.mark.intl @pytest.mark.trace @pytest.mark.version('>=3.0.6') @pytest.mark.platform('Windows') diff --git a/tests/bugs/core_5480_test.py b/tests/bugs/core_5480_test.py index 4e23bfa6..7c639ef7 100644 --- a/tests/bugs/core_5480_test.py +++ b/tests/bugs/core_5480_test.py @@ -56,6 +56,7 @@ N06 |€| """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5695_test.py b/tests/bugs/core_5695_test.py index 02e458a9..dc77d9b6 100644 --- a/tests/bugs/core_5695_test.py +++ b/tests/bugs/core_5695_test.py @@ -44,6 +44,7 @@ RES 1 """ +@pytest.mark.intl @pytest.mark.version('>=3.0.3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_5926_test.py b/tests/bugs/core_5926_test.py index 2a72675d..33eec9c7 100644 --- a/tests/bugs/core_5926_test.py +++ b/tests/bugs/core_5926_test.py @@ -32,6 +32,7 @@ test_script = temp_file('test_script.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.4') def test_1(act: Action, test_script: Path): if act.is_version('<4'): diff --git a/tests/bugs/core_6166_test.py b/tests/bugs/core_6166_test.py index fec5456c..97fb1982 100644 --- a/tests/bugs/core_6166_test.py +++ b/tests/bugs/core_6166_test.py @@ -76,6 +76,7 @@ rollback; """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_6211_test.py b/tests/bugs/core_6211_test.py index c31e2029..e0f30f0e 100644 --- a/tests/bugs/core_6211_test.py +++ b/tests/bugs/core_6211_test.py @@ -36,6 +36,7 @@ select rdb$role_name as r_name from rdb$roles where rdb$system_flag is distinct from 1; """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.isql(switches=[], input=ddl_script) diff --git a/tests/bugs/gh_0731_test.py b/tests/bugs/gh_0731_test.py index 6fdb0a94..13357886 100644 --- a/tests/bugs/gh_0731_test.py +++ b/tests/bugs/gh_0731_test.py @@ -91,6 +91,7 @@ MSG Passed """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/gh_7045_test.py b/tests/bugs/gh_7045_test.py index f41ee0e5..858448b9 100644 --- a/tests/bugs/gh_7045_test.py +++ b/tests/bugs/gh_7045_test.py @@ -25,6 +25,7 @@ act = python_act('db') +@pytest.mark.intl @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): with act.db.connect(charset='iso8859_1') as con: diff --git a/tests/bugs/gh_8015_test.py b/tests/bugs/gh_8015_test.py index c1e78eb8..094061f1 100644 --- a/tests/bugs/gh_8015_test.py +++ b/tests/bugs/gh_8015_test.py @@ -161,6 +161,7 @@ ánoc """ +@pytest.mark.intl @pytest.mark.version('>=6.0.0') def test_1(act: Action): act.expected_stdout = expected_stdout From 20af1b64103fa808a8a7a44c9ada02b6013642c6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 13:32:10 +0300 Subject: [PATCH 0228/1064] Added pytest.mark.intl to have ability filtering these files if only QA-run related to non-ascii data is needed. --- tests/bugs/core_0479_test.py | 1 + tests/bugs/core_0967_test.py | 1 + tests/bugs/core_1347_test.py | 1 + tests/bugs/core_1378_test.py | 1 + tests/bugs/core_2531_test.py | 1 + tests/bugs/core_2651_test.py | 1 + tests/bugs/core_2952_test.py | 1 + tests/bugs/core_3227_test.py | 1 + tests/bugs/core_3234_test.py | 1 + tests/bugs/core_4739_test.py | 1 + tests/bugs/core_6414_test.py | 4 ++-- tests/bugs/core_6419_test.py | 1 + tests/bugs/gh_6798_test.py | 1 + 13 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_0479_test.py b/tests/bugs/core_0479_test.py index 2c2a636c..04b98453 100644 --- a/tests/bugs/core_0479_test.py +++ b/tests/bugs/core_0479_test.py @@ -274,6 +274,7 @@ def test_1(act_1: Action): Records affected: 0 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_2(act_2: Action): act_2.expected_stdout = expected_stdout_2 diff --git a/tests/bugs/core_0967_test.py b/tests/bugs/core_0967_test.py index 0cbe2091..bbc48172 100644 --- a/tests/bugs/core_0967_test.py +++ b/tests/bugs/core_0967_test.py @@ -22,6 +22,7 @@ act = python_act('db') +@pytest.mark.intl @pytest.mark.version('>=2.1') def test_1(act: Action): with act.db.connect() as con: diff --git a/tests/bugs/core_1347_test.py b/tests/bugs/core_1347_test.py index fd1fecaf..2c7a00cb 100644 --- a/tests/bugs/core_1347_test.py +++ b/tests/bugs/core_1347_test.py @@ -57,6 +57,7 @@ and pr.rdb$procedure_name = upper('sp_test'); ''' +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action, tmp_file: Path): tmp_file.write_bytes(sql_txt.encode('cp1251')) diff --git a/tests/bugs/core_1378_test.py b/tests/bugs/core_1378_test.py index db6559c8..58280003 100644 --- a/tests/bugs/core_1378_test.py +++ b/tests/bugs/core_1378_test.py @@ -88,6 +88,7 @@ RDB$COLLATION_NAME вид прописи """ +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action, tmp_file: Path): tmp_file.write_bytes(sql_txt.encode('cp1251')) diff --git a/tests/bugs/core_2531_test.py b/tests/bugs/core_2531_test.py index cbff7c60..4913c6d4 100644 --- a/tests/bugs/core_2531_test.py +++ b/tests/bugs/core_2531_test.py @@ -45,6 +45,7 @@ Records affected: 1 """ +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): non_ascii_query = "select 'gång' as non_ascii_literal from rdb$database" diff --git a/tests/bugs/core_2651_test.py b/tests/bugs/core_2651_test.py index 05acc294..61c0a329 100644 --- a/tests/bugs/core_2651_test.py +++ b/tests/bugs/core_2651_test.py @@ -22,6 +22,7 @@ act = python_act('db') +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): with act.db.connect(charset='CP943C') as con: diff --git a/tests/bugs/core_2952_test.py b/tests/bugs/core_2952_test.py index 87d10423..3574b29c 100644 --- a/tests/bugs/core_2952_test.py +++ b/tests/bugs/core_2952_test.py @@ -2267,6 +2267,7 @@ def test_1(act_1: Action): S_WHITE_SPACE 0 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_2(act_2: Action): act_2.expected_stdout = expected_stdout_2 diff --git a/tests/bugs/core_3227_test.py b/tests/bugs/core_3227_test.py index f3ea9b00..39f30fc7 100644 --- a/tests/bugs/core_3227_test.py +++ b/tests/bugs/core_3227_test.py @@ -32,6 +32,7 @@ """ +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_3234_test.py b/tests/bugs/core_3234_test.py index 85f2d3ff..b8f5f182 100644 --- a/tests/bugs/core_3234_test.py +++ b/tests/bugs/core_3234_test.py @@ -203,6 +203,7 @@ TRIMMED_CHAR_LEN 11 """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_4739_test.py b/tests/bugs/core_4739_test.py index 90a330f0..98238d77 100644 --- a/tests/bugs/core_4739_test.py +++ b/tests/bugs/core_4739_test.py @@ -63,6 +63,7 @@ Records affected: 0 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/core_6414_test.py b/tests/bugs/core_6414_test.py index 3046673e..6d887286 100644 --- a/tests/bugs/core_6414_test.py +++ b/tests/bugs/core_6414_test.py @@ -3,8 +3,7 @@ """ ID: issue-6652 ISSUE: 6652 -TITLE: Error message "expected length N, actual M" contains wrong value of M when - charset UTF8 is used in the field declaration of a table +TITLE: Error message "expected length N, actual M" contains wrong value of M when charset UTF8 is used in the field declaration of a table DESCRIPTION: All attempts to create/alter table with not-null column with size that not enough space to fit default value must fail. Length of such column can be declared either directly or via domain - and both of these ways must fail. @@ -133,6 +132,7 @@ -expected length 1, actual 8 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stderr = expected_stderr diff --git a/tests/bugs/core_6419_test.py b/tests/bugs/core_6419_test.py index aee8b911..5acb7ddd 100644 --- a/tests/bugs/core_6419_test.py +++ b/tests/bugs/core_6419_test.py @@ -67,6 +67,7 @@ Records affected: 1 """ +@pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout diff --git a/tests/bugs/gh_6798_test.py b/tests/bugs/gh_6798_test.py index 1f51e488..daa17550 100644 --- a/tests/bugs/gh_6798_test.py +++ b/tests/bugs/gh_6798_test.py @@ -99,6 +99,7 @@ -Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. """ +@pytest.mark.intl @pytest.mark.version('>=5.0') def test_1(act: Action): act.expected_stdout = expected_stdout From 1370ed4824010ecadd26431e8d85a3e367ea9453 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 15:44:16 +0300 Subject: [PATCH 0229/1064] Added/Updated tests\bugs\gh_8214_test.py: Checked on 5.0.2.1551, 6.0.0.515. --- tests/bugs/gh_8214_test.py | 441 +++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 tests/bugs/gh_8214_test.py diff --git a/tests/bugs/gh_8214_test.py b/tests/bugs/gh_8214_test.py new file mode 100644 index 00000000..56304b19 --- /dev/null +++ b/tests/bugs/gh_8214_test.py @@ -0,0 +1,441 @@ +#coding:utf-8 + +""" +ID: issue-8214 +ISSUE: 8214 +TITLE: Incorrect result of index list scan for a composite index, the second segment of which is a text field with COLLATE UNICODE_CI +DESCRIPTION: + Test adds check for: + * collation with attributes 'case insensitive accent insensitive'; + * null values of some records (the must not appear in any query); + * non-ascii values; + * both asc and desc indices - results must be identical; + * miscelaneous predicates +NOTES: + [31.10.2024] pzotov + Confirmed bug on 5.0.2.1547. + Checked on 5.0.2.1551, 6.0.0.515. +""" + +import pytest +from firebird.qa import * + +db = db_factory(charset = 'utf8') + +test_script = """ + set bail on; + set list on; + + create collation txt_coll_ci for utf8 from unicode case insensitive; + create collation txt_coll_ci_ai for utf8 from unicode case insensitive accent insensitive; + + recreate table mans ( + id bigint not null, + code_sex smallint not null, + name_1 varchar(50) collate txt_coll_ci, + name_2 varchar(50) collate txt_coll_ci_ai, + constraint pk_mans primary key(id) + ); + + commit; + insert into mans (id, code_sex, name_1, name_2) values (1, 1, 'BoB', 'BØb'); + insert into mans (id, code_sex, name_1, name_2) values (2, 1, 'jOhN', 'jŐhŇ'); + insert into mans (id, code_sex, name_1, name_2) values (3, 2, 'BArbArA', 'BÄŔBĄŕă'); + insert into mans (id, code_sex, name_1, name_2) values (4, 2, 'aNNA', 'âŃŃÁ'); + insert into mans (id, code_sex, name_1, name_2) values (5, 1, null, null); + insert into mans (id, code_sex, name_1, name_2) values (6, 2, null, null); + insert into mans (id, code_sex, name_1, name_2) values (7, 1, 'danIEL', 'ĐÁniel'); + insert into mans (id, code_sex, name_1, name_2) values (8, 2, 'debora', 'ĐeborÁ'); + commit; + + create index mans_sex_name_1_asc on mans(code_sex, name_1); + create index mans_sex_name_2_asc on mans(code_sex, name_2); + + create view v_test_1 as + select msg, id, name_1 + from ( + select 'chk-a' as msg, id, code_sex, name_1 + from mans where code_sex between 1 and 2 and name_1 starts 'b' + UNION ALL + select 'chk-b' as msg, id, code_sex, name_1 + from mans where code_sex > 0 and code_sex < 3 and name_1 starts 'b' + UNION ALL + select 'chk-c' as msg, id, code_sex, name_1 + from mans where (code_sex =1 or code_sex =2) and name_1 starts 'b' + UNION ALL + select 'chk-d' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and name_1 starts 'b' + UNION ALL + select 'chk-e' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and name_1 like 'b%' + UNION ALL + select 'chk-f' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and name_1 similar to 'b%' + UNION ALL + select 'chk-g' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and name_1 in ('boB', 'barbarA') + UNION ALL + select 'chk-h' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and (name_1 is not distinct from 'boB' or name_1 is not distinct from 'barbarA') + UNION ALL + select 'chk-i' as msg, id, code_sex, name_1 + from mans where code_sex in(1,2) and (name_1 >= 'D' and name_1 <= 'E') + ) + order by msg, id + ; + + create view v_test_2 as + select msg, id, name_2 + from ( + select 'chk-a' as msg, id, code_sex, name_2 + from mans where code_sex between 1 and 2 and name_2 starts 'b' + UNION ALL + select 'chk-b' as msg, id, code_sex, name_2 + from mans where code_sex > 0 and code_sex < 3 and name_2 starts 'b' + UNION ALL + select 'chk-c' as msg, id, code_sex, name_2 + from mans where (code_sex =1 or code_sex =2) and name_2 starts 'b' + UNION ALL + select 'chk-d' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and name_2 starts 'b' + UNION ALL + select 'chk-e' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and name_2 like 'b%' + UNION ALL + select 'chk-f' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and name_2 similar to 'b%' + UNION ALL + select 'chk-g' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and name_2 in ('boB', 'barbarA') + UNION ALL + select 'chk-h' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and (name_2 is not distinct from 'boB' or name_2 is not distinct from 'barbarA') + UNION ALL + select 'chk-i' as msg, id, code_sex, name_2 + from mans where code_sex in(1,2) and (name_2 >= 'D' and name_2 <= 'E') + ) + order by msg, id + ; + + + select * from v_test_1; + select * from v_test_2; + commit; + + ----------------------------------------------------------- + + alter index mans_sex_name_1_asc inactive; + alter index mans_sex_name_2_asc inactive; + + create descending index mans_sex_name_1_dec on mans(code_sex, name_1); + create descending index mans_sex_name_2_dec on mans(code_sex, name_2); + commit; + + select * from v_test_1; + select * from v_test_2; +""" + +act = isql_act('db', test_script, substitutions = [ ('[ \t]+',' ') ]) + +expected_stdout = """ + MSG chk-a + ID 1 + NAME_1 BoB + + MSG chk-a + ID 3 + NAME_1 BArbArA + + MSG chk-b + ID 1 + NAME_1 BoB + + MSG chk-b + ID 3 + NAME_1 BArbArA + + MSG chk-c + ID 1 + NAME_1 BoB + + MSG chk-c + ID 3 + NAME_1 BArbArA + + MSG chk-d + ID 1 + NAME_1 BoB + + MSG chk-d + ID 3 + NAME_1 BArbArA + + MSG chk-e + ID 1 + NAME_1 BoB + + MSG chk-e + ID 3 + NAME_1 BArbArA + + MSG chk-f + ID 1 + NAME_1 BoB + + MSG chk-f + ID 3 + NAME_1 BArbArA + + MSG chk-g + ID 1 + NAME_1 BoB + + MSG chk-g + ID 3 + NAME_1 BArbArA + + MSG chk-h + ID 1 + NAME_1 BoB + + MSG chk-h + ID 3 + NAME_1 BArbArA + + MSG chk-i + ID 7 + NAME_1 danIEL + + MSG chk-i + ID 8 + NAME_1 debora + + + + MSG chk-a + ID 1 + NAME_2 BØb + + MSG chk-a + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-b + ID 1 + NAME_2 BØb + + MSG chk-b + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-c + ID 1 + NAME_2 BØb + + MSG chk-c + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-d + ID 1 + NAME_2 BØb + + MSG chk-d + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-e + ID 1 + NAME_2 BØb + + MSG chk-e + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-f + ID 1 + NAME_2 BØb + + MSG chk-f + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-g + ID 1 + NAME_2 BØb + + MSG chk-g + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-h + ID 1 + NAME_2 BØb + + MSG chk-h + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-i + ID 7 + NAME_2 ĐÁniel + + MSG chk-i + ID 8 + NAME_2 ĐeborÁ + + + + MSG chk-a + ID 1 + NAME_1 BoB + + MSG chk-a + ID 3 + NAME_1 BArbArA + + MSG chk-b + ID 1 + NAME_1 BoB + + MSG chk-b + ID 3 + NAME_1 BArbArA + + MSG chk-c + ID 1 + NAME_1 BoB + + MSG chk-c + ID 3 + NAME_1 BArbArA + + MSG chk-d + ID 1 + NAME_1 BoB + + MSG chk-d + ID 3 + NAME_1 BArbArA + + MSG chk-e + ID 1 + NAME_1 BoB + + MSG chk-e + ID 3 + NAME_1 BArbArA + + MSG chk-f + ID 1 + NAME_1 BoB + + MSG chk-f + ID 3 + NAME_1 BArbArA + + MSG chk-g + ID 1 + NAME_1 BoB + + MSG chk-g + ID 3 + NAME_1 BArbArA + + MSG chk-h + ID 1 + NAME_1 BoB + + MSG chk-h + ID 3 + NAME_1 BArbArA + + MSG chk-i + ID 7 + NAME_1 danIEL + + MSG chk-i + ID 8 + NAME_1 debora + + + + MSG chk-a + ID 1 + NAME_2 BØb + + MSG chk-a + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-b + ID 1 + NAME_2 BØb + + MSG chk-b + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-c + ID 1 + NAME_2 BØb + + MSG chk-c + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-d + ID 1 + NAME_2 BØb + + MSG chk-d + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-e + ID 1 + NAME_2 BØb + + MSG chk-e + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-f + ID 1 + NAME_2 BØb + + MSG chk-f + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-g + ID 1 + NAME_2 BØb + + MSG chk-g + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-h + ID 1 + NAME_2 BØb + + MSG chk-h + ID 3 + NAME_2 BÄŔBĄŕă + + MSG chk-i + ID 7 + NAME_2 ĐÁniel + + MSG chk-i + ID 8 + NAME_2 ĐeborÁ +""" + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From d63eb542ca453ff3ed533fd1b087fee72a209b98 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 15:47:12 +0300 Subject: [PATCH 0230/1064] Added/Updated tests\bugs\gh_8161_test.py: changed comment about explained plan in 6.x --- tests/bugs/gh_8161_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_8161_test.py b/tests/bugs/gh_8161_test.py index 28e5292f..7d50a85b 100644 --- a/tests/bugs/gh_8161_test.py +++ b/tests/bugs/gh_8161_test.py @@ -21,7 +21,10 @@ Checked on 3.0.12.33764, 4.0.5.3112, 5.0.1.1416, 6.0.0.374. [31.10.2024] pzotov - Adjusted expected_out discuss with dimitr (explained plans for FB 3.x ...6.x now are identical). + Adjusted expected_out discuss with dimitr: explained plan for FB 6.x became identical to FB 5.x and earlier after + https://github.com/FirebirdSQL/firebird/commit/e7e9e01fa9d7c13d8513fcadca102d23ad7c5e2a + ("Rework fix for #8290: Unique scan is incorrectly reported in the explained plan for unique index and IS NULL predicate") + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1551, 6.0.0.515 """ import zipfile From 920dd0fc36bd39ec6345c03b7d67ad6ffa829880 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 15:48:16 +0300 Subject: [PATCH 0231/1064] Added/Updated tests\functional\arno\optimizer\test_opt_inner_join_05.py: changed comment about explained plan in 6.x --- tests/functional/arno/optimizer/test_opt_inner_join_05.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/functional/arno/optimizer/test_opt_inner_join_05.py b/tests/functional/arno/optimizer/test_opt_inner_join_05.py index 35cbbba6..b6e2fc91 100644 --- a/tests/functional/arno/optimizer/test_opt_inner_join_05.py +++ b/tests/functional/arno/optimizer/test_opt_inner_join_05.py @@ -23,7 +23,10 @@ Checked on 6.0.0.467-cc183f5, 5.0.2.1513 [31.10.2024] pzotov - Adjusted expected_out discuss with dimitr. Explained plans for 5.x and 6.x are now identical. + Adjusted expected_out discuss with dimitr: explained plan for FB 6.x became identical to FB 5.x and earlier after + https://github.com/FirebirdSQL/firebird/commit/e7e9e01fa9d7c13d8513fcadca102d23ad7c5e2a + ("Rework fix for #8290: Unique scan is incorrectly reported in the explained plan for unique index and IS NULL predicate") + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1551, 6.0.0.515 """ From 4cf7cc1a3f4650e67ce1fc4d77852928ea300d48 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 21:38:51 +0300 Subject: [PATCH 0232/1064] Added/Updated tests\bugs\core_2912_test.py: Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1551; 4.0.6.3165; 3.0.13.33794 --- tests/bugs/core_2912_test.py | 162 +++++++++++++++++------------------ 1 file changed, 79 insertions(+), 83 deletions(-) diff --git a/tests/bugs/core_2912_test.py b/tests/bugs/core_2912_test.py index 2c6c1d61..314d0d95 100644 --- a/tests/bugs/core_2912_test.py +++ b/tests/bugs/core_2912_test.py @@ -1,83 +1,79 @@ -#coding:utf-8 - -""" -ID: issue-3296 -ISSUE: 3296 -TITLE: Exception when upper casing string with lowercase y trema (code 0xFF in ISO8859_1) -DESCRIPTION: - Test creates table and fills it with non-ascii characters in init_script, using charset = UTF8. - Then it generates .sql script for running it in separae ISQL process. - This script makes connection to test DB using charset = ISO8859_1 and perform several queries. - Result will be redirected to .log and .err files (they will be encoded, of course, also in ISO8859_1). - Finally, we open .log file (using codecs package), convert its content to UTF8 and show in expected_stdout. -JIRA: CORE-2912 -FBTEST: bugs.core_2912 -NOTES: - [16.11.2021] pcisar - This test fails as UPPER('ÿ') does not work properly - [16.09.2022] pzotov - Trouble with 'ÿ' raises only on LINUX. All fine on Windows. - Mark for running on Windows was *temporary* added to this test. Problem will be investigated. - - Checked on Windows: 3.0.8.33535, 4.0.1.2692, 5.0.0.730 -""" - -import pytest -from firebird.qa import * - -init_script = """ - create table test(c varchar(10)); - commit; - insert into test(c) values('ÿ'); - insert into test(c) values('Faÿ'); - commit; - create index test_cu on test computed by (upper (c collate iso8859_1)); - commit; -""" - -db = db_factory(charset='ISO8859_1', init=init_script) - -act = python_act('db') - -test_script = """set names ISO8859_1; - set list on; - select upper('aÿb') au from rdb$database; - select c, upper(c) cu from test where c starting with upper('ÿ'); - select c, upper(c) cu from test where c containing 'Faÿ'; - select c, upper(c) cu from test where c starting with 'Faÿ'; - select c, upper(c) cu from test where c like 'Faÿ%'; - -- ### ACHTUNG ### - -- As of WI-V2.5.4.26857, following will FAILS if character class "alpha" - -- will be specified not in UPPER case (see note in CORE-4740 08/Apr/15 05:48 PM): - select c, upper(c) cu from test where c similar to '[[:ALPHA:]]{1,}ÿ%'; - set plan on; - select c from test where upper (c collate iso8859_1) = upper('ÿ'); - select c, upper(c) cu from test where upper (c collate iso8859_1) starting with upper('Faÿ'); -""" - -expected_stdout = """ - AU AÿB - C ÿ - CU ÿ - C Faÿ - CU FAÿ - C Faÿ - CU FAÿ - C Faÿ - CU FAÿ - C Faÿ - CU FAÿ - PLAN (TEST INDEX (TEST_CU)) - C ÿ - PLAN (TEST INDEX (TEST_CU)) - C Faÿ - CU FAÿ -""" - -@pytest.mark.intl -@pytest.mark.platform('Windows') -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], charset='ISO8859_1', input=test_script) - assert act.clean_stdout == act.clean_expected_stdout +#coding:utf-8 + +""" +ID: issue-3296 +ISSUE: 3296 +TITLE: Exception when upper casing string with 'ÿ' (lowercase y trema, code 0xFF in ISO8859_1) +DESCRIPTION: +JIRA: CORE-2912 +FBTEST: bugs.core_2912 +NOTES: + [31.10.2024] pzotov + Bug was fixed for too old FB (2.1.6; 2.5.3; 3.0 Alpha 1), firebird-driver and/or QA-plugin + will not able to run on this version in order to reproduce problem. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1551; 4.0.6.3165; 3.0.13.33794 +""" +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='ISO8859_1') + +act = isql_act('db', substitutions=[('[ \\t]+', ' ')]) +tmp_sql = temp_file('tmp_core_2912.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + + test_script = """ + create table test(c varchar(10)); + commit; + insert into test(c) values('ÿ'); + insert into test(c) values('Faÿ'); + commit; + create index test_cu on test computed by (upper (c collate iso8859_1)); + commit; + set list on; + select upper('aÿb') au from rdb$database; + select c, upper(c) cu from test where c starting with upper('ÿ'); + select c, upper(c) cu from test where c containing 'Faÿ'; + select c, upper(c) cu from test where c starting with 'Faÿ'; + select c, upper(c) cu from test where c like 'Faÿ%'; + -- ### ACHTUNG ### + -- As of WI-V2.5.4.26857, following will FAILS if character class "alpha" + -- will be specified not in UPPER case (see note in CORE-4740 08/Apr/15 05:48 PM): + select c, upper(c) cu from test where c similar to '[[:ALPHA:]]{1,}ÿ%'; + set plan on; + select c from test where upper (c collate iso8859_1) = upper('ÿ'); + select c, upper(c) cu from test where upper (c collate iso8859_1) starting with upper('Faÿ'); + """ + + # ::: NB ::: + # For proper output of test, input script must be encoded in iso8859_1. + # + tmp_sql.write_text(test_script, encoding = 'iso8859_1') + + act.expected_stdout = """ + AU AÿB + C ÿ + CU ÿ + C Faÿ + CU FAÿ + C Faÿ + CU FAÿ + C Faÿ + CU FAÿ + C Faÿ + CU FAÿ + PLAN (TEST INDEX (TEST_CU)) + C ÿ + PLAN (TEST INDEX (TEST_CU)) + C Faÿ + CU FAÿ + """ + + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'iso8859_1', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From e42745b7a4f04b2d1e1dedf968613cfacec763a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 22:17:41 +0300 Subject: [PATCH 0233/1064] Added/Updated tests\functional\intfunc\string\test_lpad_01.py: Finished adjusting for work both on Linux and Windows. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33794 --- .../functional/intfunc/string/test_lpad_01.py | 184 +++++++++--------- 1 file changed, 91 insertions(+), 93 deletions(-) diff --git a/tests/functional/intfunc/string/test_lpad_01.py b/tests/functional/intfunc/string/test_lpad_01.py index 331a8f9e..cbc632e3 100644 --- a/tests/functional/intfunc/string/test_lpad_01.py +++ b/tests/functional/intfunc/string/test_lpad_01.py @@ -1,93 +1,91 @@ -#coding:utf-8 - -""" -ID: intfunc.string.lpad -TITLE: LPAD function, including non-ascii characters -DESCRIPTION: -FBTEST: functional.intfunc.string.lpad_01 -NOTES: - [03.03.2021] pzotov - Re-implemented in order to have ability to run this test on Linux. - Added tests from some COREs which have no apropriate .fbt - Test creates table and fills it with non-ascii characters using charset = UTF8. - Then it generates .sql script for running it in separate ISQL process. - This script makes connection to test DB using charset = ISO8859_1 and perform needed DML. - Result will be redirected to .log which will be opened via codecs.open(...encoding='iso-8859-1'). - Its content will be converted to UTF8 for showing in expected_stdout. - [06.10.2022] pzotov - Could not complete adjustingfor LINUX in new-qa. - DEFERRED. -""" - -import os -import platform -import pytest -from firebird.qa import * - -db = db_factory(charset='ISO8859_1') - -act = python_act('db', substitutions=[('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')]) - -test_expected_stdout = """ - ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ - ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ - TXT_LPAD_03 ¡ - ¡ - TXT_LPAD_05A ¿ - TXT_LPAD_05B À - TXT_LPAD_06A ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ - TXT_LPAD_06B ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ -""" - -test_expected_stderr = """ - Statement failed, SQLSTATE = 22001 - arithmetic exception, numeric overflow, or string truncation - -string right truncation - -expected length 32765, actual 32766 -""" - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3.0') -def test_1(act: Action): - - # NB: do NOT include here character "­ ­ soft hyphen" - # It can not be properly represented on linux in utf8 codepage! - # https://jkorpela.fi/shy.html - # - data = "¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" - - null_dev = os.devnull - test_sql = \ - f''' - set list on; - recreate table test(c varchar(32765), b blob sub_type text); - insert into test(c, b) values( '{data}', '{data}' ); - select lpad(c, 2 * char_length(c), b) as blob_id_01 from test; - select lpad(b, 2 * char_length(b), c) as blob_id_02 from test; - - -- from CORE-2745 ("build in function LPAD result is wrong if argument is longer then length to padd parameter"): - select lpad(c, 1, 'ÿ') as txt_lpad_03 from test; - select lpad(b, 1, 'ÿ') as blob_id_04 from test; - - -- from CORE-2597: LPAD result must be varchar(1) instead of varchar(32765) in this example: - select rpad('¿', 1, '¡') as txt_lpad_05a, rpad('À', 1, 'ÿ') as txt_lpad_05b from rdb$database; - - select - lpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_lpad_06a - ,lpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_lpad_06b - from rdb$database; - - out {null_dev}; - select lpad(c, 32765, c) from test; -- this must pass - select lpad(c, 32766, c) from test; -- must fail: SQLSTATE = 22001 / ... string truncation / -expected length 32765, actual 32766 - out; - - -- select char_length(lpad('', 2147483647, b)) as r_03 from test; -- <<< 152s :-) - ''' - - act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr - - act.isql(switches=['-q'], input = test_sql ) - - assert (act.clean_stdout == act.clean_expected_stdout and act.clean_stderr == act.clean_expected_stderr) +#coding:utf-8 + +""" +ID: intfunc.string.lpad +TITLE: LPAD function, including non-ascii characters +DESCRIPTION: +FBTEST: functional.intfunc.string.lpad_01 +NOTES: + [03.03.2021] pzotov + Re-implemented in order to have ability to run this test on Linux. + Added tests from some COREs which have no apropriate .fbt + Test creates table and fills it with non-ascii characters using charset = UTF8. + Then it generates .sql script for running it in separate ISQL process. + This script makes connection to test DB using charset = ISO8859_1 and perform needed DML. + + [31.10.2024] pzotov + Finished adjusting for work both on Linux and Windows. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33794 +""" +import os +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='ISO8859_1') +act = python_act('db', substitutions=[('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')]) +tmp_sql = temp_file('tmp_internal_func_lpad_01.sql') + +#@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + + # NB: do NOT include here character "­ ­ soft hyphen" + # It can not be properly represented on linux in utf8 codepage! + # https://jkorpela.fi/shy.html + # + data = "¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + + null_dev = os.devnull + test_sql = \ + f''' + set list on; + recreate table test(c varchar(32765), b blob sub_type text); + insert into test(c, b) values( '{data}', '{data}' ); + select lpad(c, 2 * char_length(c), b) as blob_id_01 from test; + select lpad(b, 2 * char_length(b), c) as blob_id_02 from test; + + -- from CORE-2745 ("build in function LPAD result is wrong if argument is longer then length to padd parameter"): + select lpad(c, 1, 'ÿ') as txt_lpad_03 from test; + select lpad(b, 1, 'ÿ') as blob_id_04 from test; + + -- from CORE-2597: LPAD result must be varchar(1) instead of varchar(32765) in this example: + select rpad('¿', 1, '¡') as txt_lpad_05a, rpad('À', 1, 'ÿ') as txt_lpad_05b from rdb$database; + + select + lpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_lpad_06a + ,lpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_lpad_06b + from rdb$database; + + out {null_dev}; + select lpad(c, 32765, c) from test; -- this must pass + select lpad(c, 32766, c) from test; -- must fail: SQLSTATE = 22001 / ... string truncation / -expected length 32765, actual 32766 + out; + + -- select char_length(lpad('', 2147483647, b)) as r_03 from test; -- <<< 152s :-) + ''' + # ::: NB ::: + # For proper output of test, input script must be encoded in iso8859_1. + # + tmp_sql.write_text(test_sql, encoding = 'iso8859_1') + + act.expected_stdout = """ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + TXT_LPAD_03 ¡ + ¡ + TXT_LPAD_05A ¿ + TXT_LPAD_05B À + TXT_LPAD_06A ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ + TXT_LPAD_06B ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ÷øùúûüýþÿ + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 32765, actual 32766 + """ + + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'iso8859_1', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 6ea13016106abcb804e4b1346b177c894a7dc1c6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 31 Oct 2024 22:23:52 +0300 Subject: [PATCH 0234/1064] Added/Updated tests\functional\intfunc\string\test_rpad_01.py: Finished adjusting for work both on Linux and Windows. Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33794 --- .../functional/intfunc/string/test_rpad_01.py | 177 +++++++++--------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/tests/functional/intfunc/string/test_rpad_01.py b/tests/functional/intfunc/string/test_rpad_01.py index eb78ea9b..de94103f 100644 --- a/tests/functional/intfunc/string/test_rpad_01.py +++ b/tests/functional/intfunc/string/test_rpad_01.py @@ -1,90 +1,87 @@ -#coding:utf-8 - -""" -ID: intfunc.string.rpad -TITLE: RPAD function, including non-ascii characters -DESCRIPTION: -NOTES: -FBTEST: functional.intfunc.string.rpad_01 -NOTES: - [03.03.2021] pzotov - Re-implemented in order to have ability to run this test on Linux. - Added tests from some COREs which have no apropriate .fbt - Test creates table and fills it with non-ascii characters using charset = UTF8. - Then it generates .sql script for running it in separate ISQL process. - This script makes connection to test DB using charset = ISO8859_1 and perform needed DML. - Result will be redirected to .log which will be opened via codecs.open(...encoding='iso-8859-1'). - Its content will be converted to UTF8 for showing in expected_stdout. - [06.10.2022] pzotov - Could not complete adjustingfor LINUX in new-qa. - DEFERRED. -""" - -import os -import platform -import pytest -from firebird.qa import * - -db = db_factory(charset='ISO8859_1') - -act = python_act('db', substitutions=[('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')]) - -test_expected_stdout = """ - ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ - ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ - TXT_RPAD_03 ¡ - ¡ - TXT_RPAD_05A ¿ - TXT_RPAD_05B À - TXT_RPAD_06A ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ - TXT_RPAD_06B ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ -""" - -test_expected_stderr = """ - Statement failed, SQLSTATE = 22001 - arithmetic exception, numeric overflow, or string truncation - -string right truncation - -expected length 32765, actual 32766 -""" - -@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes') -@pytest.mark.version('>=3.0') -def test_1(act: Action): - # NB: do NOT include here character "­ ­ soft hyphen" - # It can not be properly represented on linux in utf8 codepage! - # https://jkorpela.fi/shy.html - data = "¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" - - null_dev = os.devnull - test_sql = \ - f""" - set list on; - recreate table test(c varchar(32765), b blob sub_type text); - insert into test(c, b) values( '{data}', '{data}' ); - select rpad(c, 2 * char_length(c), b) as blob_id_01 from test; - select rpad(b, 2 * char_length(b), c) as blob_id_02 from test; - - -- from CORE-2745 ("build in function RPAD result is wrong if argument is longer then length to padd parameter"): - select rpad(c, 1, 'ÿ') as txt_rpad_03 from test; - select rpad(b, 1, 'ÿ') as blob_id_04 from test; - - -- from CORE-2597: RPAD result must be varchar(1) instead of varchar(32765) in this example: - select rpad('¿', 1, '¡') as txt_rpad_05a, rpad('À', 1, 'ÿ') as txt_rpad_05b from rdb$database; - - select - rpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_rpad_06a - ,rpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_rpad_06b - from rdb$database; - - out {null_dev}; - select rpad(c, 32765, c) from test; -- this must pass - select rpad(c, 32766, c) from test; -- must fail: SQLSTATE = 22001 / ... string truncation / -expected length 32765, actual 32766 - out; - """ - - act.expected_stdout = test_expected_stdout - act.expected_stderr = test_expected_stderr - - act.isql(switches=['-q'], input = test_sql ) - - assert (act.clean_stdout == act.clean_expected_stdout and act.clean_stderr == act.clean_expected_stderr) +#coding:utf-8 + +""" +ID: intfunc.string.rpad +TITLE: RPAD function, including non-ascii characters +DESCRIPTION: +NOTES: +FBTEST: functional.intfunc.string.rpad_01 +NOTES: + [03.03.2021] pzotov + Re-implemented in order to have ability to run this test on Linux. + Added tests from some COREs which have no apropriate .fbt + Test creates table and fills it with non-ascii characters using charset = UTF8. + Then it generates .sql script for running it in separate ISQL process. + This script makes connection to test DB using charset = ISO8859_1 and perform needed DML. + + [31.10.2024] pzotov + Finished adjusting for work both on Linux and Windows. + + Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1550; 4.0.6.3165; 3.0.13.33794 +""" +import os +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset='ISO8859_1') +act = python_act('db', substitutions=[('BLOB_ID_.*', ''), ('.*After line \\d+.*', '')]) +tmp_sql = temp_file('tmp_internal_func_rpad_01.sql') + +@pytest.mark.version('>=3.0.0') +def test_1(act: Action, tmp_sql: Path): + # NB: do NOT include here character "­ ­ soft hyphen" + # It can not be properly represented on linux in utf8 codepage! + # https://jkorpela.fi/shy.html + data = "¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + + null_dev = os.devnull + test_sql = \ + f""" + set list on; + recreate table test(c varchar(32765), b blob sub_type text); + insert into test(c, b) values( '{data}', '{data}' ); + select rpad(c, 2 * char_length(c), b) as blob_id_01 from test; + select rpad(b, 2 * char_length(b), c) as blob_id_02 from test; + + -- from CORE-2745 ("build in function RPAD result is wrong if argument is longer then length to padd parameter"): + select rpad(c, 1, 'ÿ') as txt_rpad_03 from test; + select rpad(b, 1, 'ÿ') as blob_id_04 from test; + + -- from CORE-2597: RPAD result must be varchar(1) instead of varchar(32765) in this example: + select rpad('¿', 1, '¡') as txt_rpad_05a, rpad('À', 1, 'ÿ') as txt_rpad_05b from rdb$database; + + select + rpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_rpad_06a + ,rpad('÷øùúûüýþÿ',32765-char_length('÷øùúûüýþÿ'), '{data}') as txt_rpad_06b + from rdb$database; + + out {null_dev}; + select rpad(c, 32765, c) from test; -- this must pass + select rpad(c, 32766, c) from test; -- must fail: SQLSTATE = 22001 / ... string truncation / -expected length 32765, actual 32766 + out; + """ + # ::: NB ::: + # For proper output of test, input script must be encoded in iso8859_1. + # + tmp_sql.write_text(test_sql, encoding = 'iso8859_1') + + act.expected_stdout = """ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + TXT_RPAD_03 ¡ + ¡ + TXT_RPAD_05A ¿ + TXT_RPAD_05B À + TXT_RPAD_06A ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ + TXT_RPAD_06B ÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ + + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 32765, actual 32766 + """ + + act.isql(switches = ['-q'], input_file = tmp_sql, charset = 'iso8859_1', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout \ No newline at end of file From 494488f3ec3108344fdd34e58dce2d7bb97b30f0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 1 Nov 2024 23:40:23 +0300 Subject: [PATCH 0235/1064] Added/Updated tests\bugs\gh_8185_test.py: Checked on 5.0.1.1452-08dc25f (27.07.2024 11:50); 6.0.0.401-a7d10a4 (29.07.2024 01:33) -- all OK. --- tests/bugs/gh_8185_test.py | 346 +++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 tests/bugs/gh_8185_test.py diff --git a/tests/bugs/gh_8185_test.py b/tests/bugs/gh_8185_test.py new file mode 100644 index 00000000..68cad08d --- /dev/null +++ b/tests/bugs/gh_8185_test.py @@ -0,0 +1,346 @@ +#coding:utf-8 + +""" +ID: issue-8185 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8185 +TITLE: SIGSEGV in Firebird 5.0.0.1306 embedded during update on cursor +DESCRIPTION: + Test implements sequence of actions described by Dimitry Sibiryakov in the ticket, + see: https://github.com/FirebirdSQL/firebird/issues/8185#issuecomment-2258598579 +NOTES: + [01.11.2024] pzotov + 1. Bug was fixed on following commits: + 5.x: 27.07.2024 11:48, 08dc25f8c45342a73c786bc60571c8a5f2c8c6e3 + ("Simplest fix for #8185: SIGSEGV in Firebird 5.0.0.1306 embedded during update on cursor - disallow caching for positioned updates/deletes") + 6.x: 29.07.2024 00:53, a7d10a40147d326e56540498b50e40b2da0e5850 + ("Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on") + 2. In current version of firebird-driver we can *not* set cursor name without executing it first. + But such execution leads to 'update conflict / deadlock' for subsequent UPDATE statement. + Kind of 'hack' is used to solve this problem: ps1._istmt.set_cursor_name(CURSOR_NAME) + 3. GREAT thanks to: + * Vlad for providing workaround and explanation of problem with AV for code like this: + with connect(f'localhost:{DB_NAME}', user = DBA_USER, password = DBA_PSWD) as con: + cur1 = con.cursor() + ps1 = cur1.prepare('update test set id = -id rows 0 returning id') + cur1.execute(ps1) + ps1.free() + It is mandatory to store result of cur1.eecute in some variable, i.e. rs1 = cur1.execute(ps1), + and call then rs1.close() __BEFORE__ ps1.free(). + Discussed 26.10.2024, subj: + "Oddities when using instance of selectable Statement // related to interfaces, VTable, iResultSet, iVersioned , CLOOP" + * Dimitry Sibiryakov for describe the 'step-by-step' algorithm for reproducing problem and providing working example in .cpp + + Confirmed problem on 5.0.1.1452-b056f5b (last snapshot before it was fixed). + Checked on 5.0.1.1452-08dc25f (27.07.2024 11:50); 6.0.0.401-a7d10a4 (29.07.2024 01:33) -- all OK. +""" + +import pytest +from firebird.qa import * +from firebird.driver import driver_config, connect, tpb, TraAccessMode, Isolation, DatabaseError + +init_sql = """ + set bail on; + recreate table test(id int, f01 int); + commit; + insert into test(id, f01) select row_number()over(), row_number()over() * 10 from rdb$types rows 3; + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db') + +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, capsys): + + srv_cfg = driver_config.register_server(name = 'test_srv_gh_8185', config = '') + db_cfg_name = f'db_cfg_8185' + db_cfg_object = driver_config.register_database(name = db_cfg_name) + db_cfg_object.server.value = srv_cfg.name + db_cfg_object.database.value = str(act.db.db_path) + db_cfg_object.config.value = f""" + MaxStatementCacheSize = 1M + """ + + # Pre-check: + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + cur = con.cursor() + cur.execute("select a.mon$remote_protocol, g.rdb$config_value from mon$attachments a left join rdb$config g on g.rdb$config_name = 'MaxStatementCacheSize' where a.mon$attachment_id = current_connection") + for r in cur: + conn_protocol = r[0] + db_sttm_cache_size = int(r[1]) + assert conn_protocol is None, "Test must use LOCAL protocol." + assert db_sttm_cache_size > 0, "Parameter 'MaxStatementCacheSize' (per-database) must be greater than zero for this test." + + #--------------------------------------------- + + CURSOR_NAME = 'k1' + SELECT_STTM = 'select /* ps-1*/ id, f01 from test where id > 0 for update' + UPDATE_STTM = f'update /* ps-2 */ test set id = -id where current of {CURSOR_NAME} returning id' + + update_tpb = tpb( access_mode = TraAccessMode.WRITE, + isolation = Isolation.READ_COMMITTED_RECORD_VERSION, + lock_timeout = 1) + + with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + + tx2 = con.transaction_manager(update_tpb) + tx2.begin() + + with con.cursor() as cur1, tx2.cursor() as cur2, con.cursor() as cur3: + + ps1, rs1, ps2, rs2, ps3, rs3 = None, None, None, None, None, None + try: + ps1 = cur1.prepare(SELECT_STTM) # 1. [ticket, DS] Prepare statement 1 "select ... for update" + ps1._istmt.set_cursor_name(CURSOR_NAME) # 2. [ticket, DS] Set cursor name for statement 1 // ~hack. + + # DO NOT use it because subsequent update statement will get 'deadlock / update conflict' and not able to start: + #rs1 = cur1.execute(ps1) + #cur1.set_cursor_name(CURSOR_NAME) + + # DS example: "// Prepare positioned update statement" + ps2 = cur2.prepare(UPDATE_STTM) # 3. [ticket, DS] Prepare statement 2 "update ... where current of " + + # DS .cpp: // fetch records from cursor and print them + rs1 = cur1.execute(ps1) + rs1.fetchall() + + # DS .cpp: // IStatement* stmt2 = att->prepare(&status, tra, 0, "select * from pos where a > 1 for update", + ps3 = cur3.prepare(SELECT_STTM) # 4. [ticket, DS] Prepare statement 3 similar to statement 1 + + rs1.close() # 5. [ticket, DS] Release statement 1 // see hvlad recipe, 26.10.2024 + ps1.free() + + # DS .cpp: updStmt->free(&status); + ps2.free() # 6. [ticket, DS] Release statement 2 // see hvlad recipe, 26.10.2024 + + # DS .cpp: stmt = stmt2 + ps3._istmt.set_cursor_name(CURSOR_NAME) # 7. [ticket, DS] Set cursor name to statement 3 as in step 2 + + ps2 = cur2.prepare(UPDATE_STTM) # 8. [ticket, DS] Prepare statement 2 again (it will be got from cache keeping reference to statement 1) + + rs3 = cur3.execute(ps3) + rs3.fetchone() # 9. [ticket, DS] Run statement 3 and fetch one record + + # At step 10 you can get "Invalid handle" error or a crash if you swap steps 5 and 6. + rs2 = cur2.execute(ps2) # 10. [ticket, DS] Execute statement 2 + data2 = rs2.fetchone() + print('Changed ID:', data2[0]) + # print(f'{rs2.rowcount=}') + + except DatabaseError as e: + print(e.__str__()) + print('gds codes:') + for i in e.gds_codes: + print(i) + + finally: + if rs1: + rs1.close() + if ps1: + ps1.free() + + if rs2: + rs2.close() + if ps2: + ps2.free() + + if rs3: + rs3.close() + if ps3: + ps3.free() + + #--------------------------------------------- + + act.expected_stdout = 'Changed ID: -1' + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + + +# Example in .cpp (provided by Dimitry Sibiryakov): +################################################### +# +# #include +# #include "ifaceExamples.h" +# static IMaster* master = fb_get_master_interface(); +# +# int main() +# { +# int rc = 0; +# +# // status vector and main dispatcher +# ThrowStatusWrapper status(master->getStatus()); +# IProvider* prov = master->getDispatcher(); +# IUtil* utl = master->getUtilInterface(); +# +# // declare pointers to required interfaces +# IAttachment* att = NULL; +# ITransaction* tra = NULL; +# IStatement* stmt = NULL; +# IMessageMetadata* meta = NULL; +# IMetadataBuilder* builder = NULL; +# IXpbBuilder* tpb = NULL; +# +# // Interface provides access to data returned by SELECT statement +# IResultSet* curs = NULL; +# +# try +# { +# // IXpbBuilder is used to access various parameters blocks used in API +# IXpbBuilder* dpb = NULL; +# +# // create DPB - use non-default page size 4Kb +# dpb = utl->getXpbBuilder(&status, IXpbBuilder::DPB, NULL, 0); +# dpb->insertString(&status, isc_dpb_user_name, "sysdba"); +# dpb->insertString(&status, isc_dpb_password, "masterkey"); +# +# // create empty database +# att = prov->attachDatabase(&status, "ctest", dpb->getBufferLength(&status), +# dpb->getBuffer(&status)); +# +# dpb->dispose(); +# +# printf("database attached.\n"); +# +# att->execute(&status, nullptr, 0, "set debug option dsql_keep_blr = true", SAMPLES_DIALECT, nullptr, nullptr, nullptr, nullptr); +# // start read only transaction +# tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0); +# tpb->insertTag(&status, isc_tpb_read_committed); +# tpb->insertTag(&status, isc_tpb_no_rec_version); +# tpb->insertTag(&status, isc_tpb_wait); +# tra = att->startTransaction(&status, tpb->getBufferLength(&status), tpb->getBuffer(&status)); +# +# // prepare statement +# stmt = att->prepare(&status, tra, 0, "select * from pos where a > 1 for update", +# SAMPLES_DIALECT, IStatement::PREPARE_PREFETCH_METADATA); +# +# // get list of columns +# meta = stmt->getOutputMetadata(&status); +# unsigned cols = meta->getCount(&status); +# unsigned messageLength = meta->getMessageLength(&status); +# +# std::unique_ptr buffer(new char[messageLength]); +# +# stmt->setCursorName(&status, "abc"); +# +# // open cursor +# printf("Opening cursor...\n"); +# curs = stmt->openCursor(&status, tra, NULL, NULL, meta, 0); +# +# // Prepare positioned update statement +# printf("Preparing update statement...\n"); +# IStatement* updStmt = att->prepare(&status, tra, 0, "update pos set b=b+1 where current of abc", +# SAMPLES_DIALECT, 0); +# +# const unsigned char items[] = {isc_info_sql_exec_path_blr_text, isc_info_sql_explain_plan}; +# unsigned char infoBuffer[32000]; +# updStmt->getInfo(&status, sizeof items, items, sizeof infoBuffer, infoBuffer); +# +# IXpbBuilder* pb = utl->getXpbBuilder(&status, IXpbBuilder::INFO_RESPONSE, infoBuffer, sizeof infoBuffer); +# for (pb->rewind(&status); !pb->isEof(&status); pb->moveNext(&status)) +# { +# switch (pb->getTag(&status)) +# { +# case isc_info_sql_exec_path_blr_text: +# printf("BLR:\n%s\n", pb->getString(&status)); +# break; +# case isc_info_sql_explain_plan: +# printf("Plan:\n%s\n", pb->getString(&status)); +# break; +# case isc_info_truncated: +# printf(" truncated\n"); +# // fall down... +# case isc_info_end: +# break; +# default: +# printf("Unexpected item %d\n", pb->getTag(&status)); +# } +# } +# pb->dispose(); +# +# // fetch records from cursor and print them +# for (int line = 0; curs->fetchNext(&status, buffer.get()) == IStatus::RESULT_OK; ++line) +# { +# printf("Fetched record %d\n", line); +# updStmt->execute(&status, tra, nullptr, nullptr, nullptr, nullptr); +# printf("Update executed\n"); +# } +# +# IStatement* stmt2 = att->prepare(&status, tra, 0, "select * from pos where a > 1 for update", +# SAMPLES_DIALECT, IStatement::PREPARE_PREFETCH_METADATA); +# +# // close interfaces +# curs->close(&status); +# curs = NULL; +# +# stmt->free(&status); +# stmt = NULL; +# +# updStmt->free(&status); +# +# stmt = stmt2; +# stmt->setCursorName(&status, "abc"); +# +# // open cursor +# printf("Opening cursor2...\n"); +# curs = stmt->openCursor(&status, tra, NULL, NULL, meta, 0); +# +# // Prepare positioned update statement +# printf("Preparing update statement again...\n"); +# updStmt = att->prepare(&status, tra, 0, "update pos set b=b+1 where current of abc", +# SAMPLES_DIALECT, 0); +# +# // fetch records from cursor and print them +# for (int line = 0; curs->fetchNext(&status, buffer.get()) == IStatus::RESULT_OK; ++line) +# { +# printf("Fetched record %d\n", line); +# updStmt->execute(&status, tra, nullptr, nullptr, nullptr, nullptr); +# printf("Update executed\n"); +# } +# +# curs->close(&status); +# curs = NULL; +# +# stmt->free(&status); +# stmt = NULL; +# +# updStmt->free(&status); +# +# meta->release(); +# meta = NULL; +# +# tra->commit(&status); +# tra = NULL; +# +# att->detach(&status); +# att = NULL; +# } +# catch (const FbException& error) +# { +# // handle error +# rc = 1; +# +# char buf[256]; +# master->getUtilInterface()->formatStatus(buf, sizeof(buf), error.getStatus()); +# fprintf(stderr, "%s\n", buf); +# } +# +# // release interfaces after error caught +# if (meta) +# meta->release(); +# if (builder) +# builder->release(); +# if (curs) +# curs->release(); +# if (stmt) +# stmt->release(); +# if (tra) +# tra->release(); +# if (att) +# att->release(); +# if (tpb) +# tpb->dispose(); +# +# prov->release(); +# status.dispose(); +# +# return rc; +# } From 87dfaf7f429caea8cc134a9b51e399a3c9cdbf27 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 2 Nov 2024 22:22:57 +0300 Subject: [PATCH 0236/1064] Added/Updated tests\bugs\gh_5009_test.py: Checked on 4.0.6.3165, 5.0.2.1551, 6.0.0.415 --- tests/bugs/gh_5009_test.py | 103 +++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/bugs/gh_5009_test.py diff --git a/tests/bugs/gh_5009_test.py b/tests/bugs/gh_5009_test.py new file mode 100644 index 00000000..24f4aab5 --- /dev/null +++ b/tests/bugs/gh_5009_test.py @@ -0,0 +1,103 @@ +#coding:utf-8 + +""" +ID: issue-5009 +ISSUE: 5009 +TITLE: Index and blob garbage collection doesn't take into accout data in undo log [CORE4701] +DESCRIPTION: +JIRA: CORE-4701 +NOTES: + [02.11.2024] pzotov + Confirmed bug on 3.0.13.33794. + Checked on 4.0.6.3165, 5.0.2.1551, 6.0.0.415 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + create table g_test (f integer); + create index g_ind on g_test (f); + insert into g_test values (1); + commit; + update g_test set f=2; + savepoint a; + update g_test set f=3; + savepoint b; + update g_test set f=3; + savepoint c; + update g_test set f=4; + savepoint d; + update g_test set f=4; + release savepoint b only; + rollback to savepoint c; + commit; + set list on; + set count on; + set plan on; + + select g.f as f_natreads from g_test g; + + select g.f as f_idxreads from g_test g where g.f between 1 and 4; +""" + +act = isql_act('db', test_script, substitutions = [ ('[ \t]+', ' '), ]) + +@pytest.mark.version('>=4.0.0') +def test_1(act: Action, capsys): + + act.execute(combine_output = True) + + act.expected_stdout = """ + PLAN (G NATURAL) + F_NATREADS 3 + Records affected: 1 + PLAN (G INDEX (G_IND)) + F_IDXREADS 3 + Records affected: 1 + """ + + with act.connect_server() as srv: + srv.database.validate(database = act.db.db_path) + validate_err = '\n'.join( [line for line in srv if 'ERROR' in line.upper()] ) + + expected_isql = 'ISQL output check: PASSED.' + expected_onlv = 'Online validation: FAILED.' + + if act.clean_stdout == act.clean_expected_stdout: + print(expected_isql) + else: + print( + f""" + ISQL output check: FAILED. + Actual: + {act.clean_stdout} + Expected: + {act.expected_stdout} + """ + ) + + if not validate_err: + print(expected_onlv) + else: + print( + f""" + Online validation: FAILED. + Actual: + {validate_err} + Epsected: + + """ + ) + + + act.reset() + act.expected_stdout = f""" + {expected_isql} + {expected_onlv} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + From 2a969614c5598e7cfd2d04a0f26ebdfc95f3e098 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 2 Nov 2024 23:42:00 +0300 Subject: [PATCH 0237/1064] Added/Updated tests\bugs\gh_7269_test.py: Checked on 5.0.2.1551, 6.0.0.415. --- tests/bugs/gh_7269_test.py | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/bugs/gh_7269_test.py diff --git a/tests/bugs/gh_7269_test.py b/tests/bugs/gh_7269_test.py new file mode 100644 index 00000000..aaae9140 --- /dev/null +++ b/tests/bugs/gh_7269_test.py @@ -0,0 +1,68 @@ +#coding:utf-8 + +""" +ID: issue-7269 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7269 +TITLE: Database restore must make every effort on activating deferred indexes +DESCRIPTION: + Test uses unrecoverable .fbk that was provided in the ticket and tries to restore it using '-verbose' option. + After restore finish, we check its log. It must contain SEVERAL errors related to indices (PK and two FK), + and also it must have messages about FINAL point of restore (regardless error that follows after this): + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags +NOTES: + [02.11.2024] pzotov + Checked on 5.0.2.1551, 6.0.0.415. +""" +import subprocess +from pathlib import Path +import zipfile +import locale +import re +import pytest +from firebird.qa import * +from firebird.driver import SrvRestoreFlag + +db = db_factory() +act = python_act('db') +tmp_fbk = temp_file('gh_7269.tmp.fbk') +tmp_fdb = temp_file('gh_7269.tmp.fdb') + +@pytest.mark.version('>=4.0.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_7269.zip', at = 'gh-7269-unrecoverable.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + allowed_patterns = \ + ( + r'gbak:(\s+)?ERROR(:)?' + ,r'gbak:(\s+)?finishing, closing, and going home' + ,r'gbak:(\s+)?adjusting the ONLINE and FORCED WRITES flags' + ) + allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in allowed_patterns ] + + act.gbak(switches = ['-rep', '-v', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) + + for line in act.stdout.splitlines(): + if act.match_any(line.strip(), allowed_patterns): + print(line) + + expected_stdout = """ + gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A3" on table "A3" + gbak: ERROR: Problematic key value is ("ID" = 9) + gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A1" on table "A1" + gbak: ERROR: Problematic key value is ("ID" = 5) + gbak: ERROR:Cannot create foreign key constraint FK_A1. Partner index does not exist or is inactive. + gbak: ERROR:violation of FOREIGN KEY constraint "FK_A2" on table "B2" + gbak: ERROR: Foreign key reference target does not exist + gbak: ERROR: Problematic key value is ("A2_ID" = 5) + gbak: ERROR:Cannot create foreign key constraint FK_A3. Partner index does not exist or is inactive. + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + gbak: ERROR:Database is not online due to failure to activate one or more indices. + gbak: ERROR: Run gfix -online to bring database online without active indices. + """ + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 524b195208c173db391b3fb8adf097e938db129b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 3 Nov 2024 09:53:56 +0300 Subject: [PATCH 0238/1064] Added forgotten .zip that is needed for appropriate test --- files/gh_7269.zip | Bin 0 -> 1185 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_7269.zip diff --git a/files/gh_7269.zip b/files/gh_7269.zip new file mode 100644 index 0000000000000000000000000000000000000000..956db23a389e3ee962ab7f25d31e4e4e53001e37 GIT binary patch literal 1185 zcmWIWW@Zs#U|`^2DBqS8xzg@H`%7jZSB8N>5=fr9r0y%J;2?a9xrv8Y#ja(;-4f}1&CKOlu~v7UCHjlXGaplyx1Ym) zL|AC!-6LB)ch44GXlrmX?oRQ$o!{p~#!l$I&7s&cH|hIRxdahKkyFpZet*7xSwDXM z-umyyZqBOvBc^)a&Lu@(X|DLkcil7GzF01O@vHRB$)Zq+RF2rGPy6)T&#|357Ae28 z@BHO^e4K?52I~@H-sEmv$h*^iYPIKL#X5z|*p=2c}4dnB&hExyxoXM(xW7xndS)^k@Me3CNh+ob5O z2HEl%yI#e`O_tYvT_3$F=j8L>pMENqO<_4VY4JXxh1Z|7S6M_K+3Ip-f&UegTtofX zIp%S8`oE<=mtC7bUH9DWSiAf`=Fi@)v&}!hgMatw=Xdvh*i+|}w)E6InTXYMj5oY3 z|1VV*{_E?xui1B&?~U63S--=S=W?W~v)-GCtCzp(N{1KKx2A4uOI@a0er=1)`gBW? zX%pZ7INrWlu2}W(;d%ew$4TUQu2bOUOYd}@)KRpgV&McY2`-sE!7}-etdG9?=hU}& z+Uq_4^bT0FX-sFhf2Cnw1XE2kbJ9kZAM4n@92I(y$t%&Jdf>Zhg0~K1-3mr$pu|SD zoNmJxs(oUjJJi)^b{au;}=XIu3oXMxvQwpB-f)M>U=OMp}+pDbAR6c%|l?Q>LPM+y$HmugLiMJ`7p6 zvLL#_n`0T+j8Cdps{OKO`2J=$e$;leLMruV#*>|#2lLFnb%zQ(%deF_UQ;pU!{iqm z>NlO>5Lq{M#X^@{)hzA6;La@7G!4V(&YNCmLXx6ZZeDR^^WCpG<+B7eVg%T=+78b6 z-p+n={*gvW=bSA|%Dk=F&T@#vZCm2zJ=wzG^D8OcnRhRp^EPH`ovu4GFH=~wZ;=t- z*W=$mEO^oBd~d$b&ks+pte@wl7V1-FH(66H`rw^w)33=c`{i*~*|=Z!v&8J<>ulm2 zr$2aZ9^lQ$WY2)BgiryN5g?!dCh?RPTu>#93=$0SA9R-{=-y_`xwYbJ3Xq2J1H4(; PK;|$4VK$IfU;*&}ns69Z literal 0 HcmV?d00001 From 0f4c5acfef3b040d94ba7811adfbf669331da098 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 4 Nov 2024 10:03:27 +0300 Subject: [PATCH 0239/1064] Added/Updated tests\bugs\gh_7269_test.py: fixed wrong min_version --- tests/bugs/gh_7269_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_7269_test.py b/tests/bugs/gh_7269_test.py index aaae9140..a19440ad 100644 --- a/tests/bugs/gh_7269_test.py +++ b/tests/bugs/gh_7269_test.py @@ -28,7 +28,7 @@ tmp_fbk = temp_file('gh_7269.tmp.fbk') tmp_fdb = temp_file('gh_7269.tmp.fdb') -@pytest.mark.version('>=4.0.0') +@pytest.mark.version('>=5.0.2') def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_7269.zip', at = 'gh-7269-unrecoverable.fbk') tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) From 718804e976c7ea64fe37bc190a9e1a150c8a2f36 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 4 Nov 2024 12:37:18 +0300 Subject: [PATCH 0240/1064] Added/Updated tests\bugs\gh_8304_test.py: Checked on 6.0.0.515-1c3dc43; 5.0.2.1551-90fdb97; 4.0.6.3165 (intermediate build). --- tests/bugs/gh_8304_test.py | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tests/bugs/gh_8304_test.py diff --git a/tests/bugs/gh_8304_test.py b/tests/bugs/gh_8304_test.py new file mode 100644 index 00000000..6260f53e --- /dev/null +++ b/tests/bugs/gh_8304_test.py @@ -0,0 +1,96 @@ +#coding:utf-8 + +""" +ID: issue-8304 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8304 +TITLE: wrong results using minvalue/maxvalue in join condition +DESCRIPTION: +NOTES: + [04.11.2024] pzotov + Confirmed bug on 6.0.0.515-d53f368 (dob: 30.10.2024). + Checked on 6.0.0.515-1c3dc43; 5.0.2.1551-90fdb97; 4.0.6.3165 (intermediate build). +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + create domain dm_sml smallint default 0 not null; + create domain dm_txt varchar(100) not null; + create table tbl1 ( + ds int, + ru dm_sml, + wi dm_sml, + ko dm_sml + ); + + create table tbl2 ( + id int, + ru dm_sml, + ru_txt dm_txt, + wi dm_sml, + wi_txt dm_txt, + ko dm_sml, + ko_txt dm_txt + ); + + commit; + + insert into tbl1 (ds, ru, wi, ko) values(50, 1, 1, 0); + + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(1, 1, 'a', 1, 'a', 1, 'a'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(2, 1, 'b', 1, 'b', 0, 'b'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(3, 1, 'c', 0, 'c', 1, 'c'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(4, 1, 'd', 0, 'd', 0, 'd'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(5, 0, 'e', 1, 'e', 1, 'e'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(6, 0, 'f', 1, 'f', 0, 'f'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(7, 0, 'g', 0, 'g', 1, 'g'); + insert into tbl2 (id, ru, ru_txt, wi, wi_txt, ko, ko_txt) values(8, 0, 'h', 0, 'h', 0, 'h'); + + commit; + + set count on; + set list on; + + -- no record - wrong: + select 'case-1' as msg, a.* + from tbl1 a + join tbl2 b on minvalue(a.ko, 1) = b.ko and + minvalue(a.ru, 1) = b.ru and + minvalue(a.wi, 1) = b.wi + ; + + -- one record - correct: + select 'case-2' as msg, a.* + from tbl1 a + join tbl2 b on decode(a.ko, 0, 0, 1) = b.ko and + decode(a.ru, 0, 0, 1) = b.ru and + decode(a.wi, 0, 0, 1) = b.wi + ; +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + MSG case-1 + DS 50 + RU 1 + WI 1 + KO 0 + Records affected: 1 + + MSG case-2 + DS 50 + RU 1 + WI 1 + KO 0 + Records affected: 1 +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From aeb3dbe22dc4fb8eafc15bf7f3e9d137ca6eb4f0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 7 Nov 2024 16:09:24 +0300 Subject: [PATCH 0241/1064] Added/Updated tests\bugs\core_2668_test.py: Confirmed problem on 5.0.0.731. Checked on 5.0.0.733 (16.09.2022); 5.0.2.1553, 6.0.0.515 --- tests/bugs/core_2668_test.py | 244 ++++++++++++++++++++++++++--------- 1 file changed, 183 insertions(+), 61 deletions(-) diff --git a/tests/bugs/core_2668_test.py b/tests/bugs/core_2668_test.py index e98a8921..a812742e 100644 --- a/tests/bugs/core_2668_test.py +++ b/tests/bugs/core_2668_test.py @@ -5,92 +5,214 @@ ISSUE: 3072 TITLE: Write note into log when automatic sweep is started DESCRIPTION: + Test changes sweep interval to some low value (see SWEEP_GAP) and runs TX_COUNT transactions which + lead difference between OST and OIT to exceed given sweep interval. These transactions are performed + by ISQL which is launched as child process. SQL script uses table with record that is locked at the + beginning of script and execute block with loop of TX_COUNT statements which insert new records. + After this loop finish, we make ISQL to hang by forcing it to update first record (see LOCKED_ROW). + Then we change DB state to full shutdown and wait until ISQL will be terminated. + At this point database has sweep gap that is enough to run auto sweep at first connection to DB. + Finally, we bring DB online and start trace with log_sweep = true and log_transactions = true. + Doing connection and wait about 2..3 seconds cause auto sweep to be started and completed. + This must be reflected in the trace. + + If ServerMode = 'Super' and ParallelWorkers >= 2 and MaxParallelWorkers >= ParallelWorkers + then trace log will contain folloing five lines related to worker(s) activity: + (...) START_TRANSACTION + (ATT_..., , NONE, ) --------------------- [ 1 ] + (TRA_..., READ_COMMITTED | REC_VERSION | WAIT | READ_ONLY) + (...) COMMIT_TRANSACTION + (ATT_..., , NONE, ) --------------------- [ 2 ] + + This is the only difference that can be observed for snapshots before and after fix + (i.e. BEFORE fix trace had no such lines but all other data about sweep *did* present). + Test checks that trace log contains TWO lines with '', see above [ 1 ] and [ 2 ]. + JIRA: CORE-2668 FBTEST: bugs.core_2668 +NOTES: + [07.11.2024] pzotov + Confirmed absense of lines marked as ',\s+NONE,\s+\)', re.IGNORECASE) +################ + +tmp_sql = temp_file('tmp_2668.sql') +tmp_log = temp_file('tmp_2668.log') -act = python_act('db') +@pytest.mark.es_eds +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): + + if act.vars['server-arch'] != 'SuperServer': + pytest.skip("Applies only to SuperServer") -test_script = """ -recreate table test(s varchar(36) unique); -insert into test(s) values('LOCKED_FOR_PAUSE'); -commit; + with act.db.connect() as con: + cur = con.cursor() + sql = """ + select + cast(max(iif(g.rdb$config_name = 'ParallelWorkers', g.rdb$config_value, null)) as int) as cfg_par_workers + ,cast(max(iif(g.rdb$config_name = 'MaxParallelWorkers', g.rdb$config_value, null)) as int) as cfg_max_par_workers + from rdb$database + left join rdb$config g on g.rdb$config_name in ('ParallelWorkers', 'MaxParallelWorkers') + """ + cur.execute(sql) + cfg_par_workers, cfg_max_par_workers = cur.fetchone() -set transaction read committed WAIT; + assert cfg_par_workers >=2 and cfg_max_par_workers >= cfg_par_workers, "Server must be configured for parallel work. Check values of ParallelWorkers and MaxParallelWorkers" -update test set s = s where s = 'LOCKED_FOR_PAUSE'; + test_script = f""" + set echo on; + set bail on; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; -set term ^; -execute block as - declare n int = 150; - declare v_role varchar(31); -begin - while (n > 0) do - in autonomous transaction do - insert into test(s) values( rpad('', 36, uuid_to_char(gen_uuid()) ) ) - returning :n-1 into n; + recreate table test(id int primary key); + insert into test(id) values({LOCKED_ROW}); + commit; - v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); + set transaction read committed WAIT; - begin - execute statement ('update test set s = s where s = ?') ('LOCKED_FOR_PAUSE') - on external - 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user 'SYSDBA' password 'masterkey' role v_role - with autonomous transaction; - when any do + update test set id = id where id = {LOCKED_ROW}; + set term ^; + execute block as + declare n int = {TX_COUNT}; + declare v_role varchar(31); begin - end - end + while (n > 0) do + in autonomous transaction do + insert into test(id) values(:n) + returning :n-1 into n; -end -^ -set term ;^ -set heading off; -select '-- shutdown me now --' from rdb$database; -""" + v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); -tmp_script = temp_file('work_script.sql') + begin + execute statement ('update test /* ' || ascii_char(65) || ' */ set id = id where id = ?') ({LOCKED_ROW}) + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user '{act.db.user}' password '{act.db.password}' role v_role + with autonomous transaction; + when any do + begin + end + end -@pytest.mark.es_eds -@pytest.mark.version('>=3') -def test_1(act: Action, tmp_script: Path): - tmp_script.write_text(test_script) + end + ^ + set term ;^ + set heading off; + select '-- shutdown me now --' from rdb$database; + """ + + tmp_sql.write_text(test_script) with act.connect_server() as srv: - srv.database.set_sweep_interval(database=act.db.db_path, interval=100) + ############################## + ### reduce SWEEEP interval ### + ############################## + srv.database.set_sweep_interval(database = act.db.db_path, interval = SWEEP_GAP) srv.database.set_write_mode(database=act.db.db_path, mode=DbWriteMode.ASYNC) - p_work_sql = subprocess.Popen([act.vars['isql'], '-i', str(tmp_script), - '-user', act.db.user, - '-password', act.db.password, act.db.dsn], - stderr = subprocess.STDOUT) - time.sleep(3) - try: - srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, - method=ShutdownMethod.FORCED, timeout=0) - finally: - p_work_sql.terminate() + + with open(tmp_log,'w') as f_log: + p_work_sql = subprocess.Popen([act.vars['isql'], '-q', '-i', str(tmp_sql)], stdout = f_log, stderr = subprocess.STDOUT) + + chk_mon_sql = """ + select 1 + from mon$attachments a + join mon$statements s + using (mon$attachment_id) + where + a.mon$attachment_id <> current_connection + and cast(s.mon$sql_text as varchar(8192)) containing '/* A */' + """ + + found_in_mon_tables = False + with act.db.connect() as con_watcher: + + custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) + tx_watcher = con_watcher.transaction_manager(custom_tpb) + cur_watcher = tx_watcher.cursor() + + ps = cur_watcher.prepare(chk_mon_sql) + + i = 0 + da = dt.now() + while True: + cur_watcher.execute(ps) + mon_result = -1 + for r in cur_watcher: + mon_result = r[0] + + tx_watcher.commit() + db = dt.now() + diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 + if mon_result == 1: + found_in_mon_tables = True + break + elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: + break + + time.sleep(0.1) + + ps.free() + + assert found_in_mon_tables, f'Could not find attachment in mon$ tables for {MAX_WAIT_FOR_ISQL_PID_APPEARS_MS} ms.' + + try: + ############################################## + ### f u l l s h u t d o w n D B ### + ############################################## + srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + finally: + p_work_sql.terminate() + # < with open(tmp_log,'w') as f_log + srv.database.bring_online(database=act.db.db_path) - srv.info.get_log() - fblog_before = srv.readlines() + + trace_options = \ + [ + 'time_threshold = 0' + ,'log_initfini = false' + ,'log_connections = true' + ,'log_transactions = true' + ,'log_errors = true' + ,'log_sweep = true' + ] + + with act.trace(db_events = trace_options, encoding='utf8', encoding_errors='utf8'): with act.db.connect() as con_for_sweep_start: - con_for_sweep_start.begin() time.sleep(2) - srv.info.get_log() - fblog_after = srv.readlines() - pattern = re.compile('Sweep\\s+.*SWEEPER', re.IGNORECASE) - success = False - for line in unified_diff(fblog_before, fblog_after): - if line.startswith('+') and pattern.search(line): - success = True - assert success + + + for line in act.trace_log: + if WATCH_FOR_PTN.search(line): + print(WATCH_FOR_PTN.search(line).group()) + + act.expected_stdout = """ + (ATT_N, , NONE, ) + (ATT_N, , NONE, ) + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From ea96df900b911082f8b9a397f6a7b9d8d52abece Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 7 Nov 2024 16:12:20 +0300 Subject: [PATCH 0242/1064] Added/Updated tests\bugs\gh_7304_test.py: Confirmed problem on 5.0.0.731. Checked on 5.0.0.733 (16.09.2022); 5.0.2.1553, 6.0.0.515 --- tests/bugs/gh_7304_test.py | 218 +++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 tests/bugs/gh_7304_test.py diff --git a/tests/bugs/gh_7304_test.py b/tests/bugs/gh_7304_test.py new file mode 100644 index 00000000..0c1a3c2d --- /dev/null +++ b/tests/bugs/gh_7304_test.py @@ -0,0 +1,218 @@ +#coding:utf-8 + +""" +ID: issue-7304 +ISSUE: 7304 +TITLE: Events in system attachments (like garbage collector) are not traced +DESCRIPTION: + Test changes sweep interval to some low value (see SWEEP_GAP) and runs TX_COUNT transactions which + lead difference between OST and OIT to exceed given sweep interval. These transactions are performed + by ISQL which is launched as child process. SQL script uses table with record that is locked at the + beginning of script and execute block with loop of TX_COUNT statements which insert new records. + After this loop finish, we make ISQL to hang by forcing it to update first record (see LOCKED_ROW). + Then we change DB state to full shutdown and wait until ISQL will be terminated. + At this point database has sweep gap that is enough to run auto sweep at first connection to DB. + Finally, we bring DB online and start trace with log_sweep = true and log_transactions = true. + Doing connection and wait about 2..3 seconds cause auto sweep to be started and completed. + This must be reflected in the trace. + + If ServerMode = 'Super' and ParallelWorkers >= 2 and MaxParallelWorkers >= ParallelWorkers + then trace log will contain folloing five lines related to worker(s) activity: + (...) START_TRANSACTION + (ATT_..., , NONE, ) --------------------- [ 1 ] + (TRA_..., READ_COMMITTED | REC_VERSION | WAIT | READ_ONLY) + (...) COMMIT_TRANSACTION + (ATT_..., , NONE, ) --------------------- [ 2 ] + + This is the only difference that can be observed for snapshots before and after fix + (i.e. BEFORE fix trace had no such lines but all other data about sweep *did* present). + Test checks that trace log contains TWO lines with '', see above [ 1 ] and [ 2 ]. + +JIRA: CORE-2668 +FBTEST: bugs.core_2668 +NOTES: + [07.11.2024] pzotov + Confirmed absense of lines marked as ',\s+NONE,\s+\)', re.IGNORECASE) +################ + +tmp_sql = temp_file('tmp_2668.sql') +tmp_log = temp_file('tmp_2668.log') + +@pytest.mark.es_eds +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): + + if act.vars['server-arch'] != 'SuperServer': + pytest.skip("Applies only to SuperServer") + + with act.db.connect() as con: + cur = con.cursor() + sql = """ + select + cast(max(iif(g.rdb$config_name = 'ParallelWorkers', g.rdb$config_value, null)) as int) as cfg_par_workers + ,cast(max(iif(g.rdb$config_name = 'MaxParallelWorkers', g.rdb$config_value, null)) as int) as cfg_max_par_workers + from rdb$database + left join rdb$config g on g.rdb$config_name in ('ParallelWorkers', 'MaxParallelWorkers') + """ + cur.execute(sql) + cfg_par_workers, cfg_max_par_workers = cur.fetchone() + + assert cfg_par_workers >=2 and cfg_max_par_workers >= cfg_par_workers, "Server must be configured for parallel work. Check values of ParallelWorkers and MaxParallelWorkers" + + test_script = f""" + set echo on; + set bail on; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + + recreate table test(id int primary key); + insert into test(id) values({LOCKED_ROW}); + commit; + + set transaction read committed WAIT; + + update test set id = id where id = {LOCKED_ROW}; + set term ^; + execute block as + declare n int = {TX_COUNT}; + declare v_role varchar(31); + begin + while (n > 0) do + in autonomous transaction do + insert into test(id) values(:n) + returning :n-1 into n; + + v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); + + begin + execute statement ('update test /* ' || ascii_char(65) || ' */ set id = id where id = ?') ({LOCKED_ROW}) + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user '{act.db.user}' password '{act.db.password}' role v_role + with autonomous transaction; + when any do + begin + end + end + + end + ^ + set term ;^ + set heading off; + select '-- shutdown me now --' from rdb$database; + """ + + tmp_sql.write_text(test_script) + with act.connect_server() as srv: + ############################## + ### reduce SWEEEP interval ### + ############################## + srv.database.set_sweep_interval(database = act.db.db_path, interval = SWEEP_GAP) + srv.database.set_write_mode(database=act.db.db_path, mode=DbWriteMode.ASYNC) + + with open(tmp_log,'w') as f_log: + p_work_sql = subprocess.Popen([act.vars['isql'], '-q', '-i', str(tmp_sql)], stdout = f_log, stderr = subprocess.STDOUT) + + chk_mon_sql = """ + select 1 + from mon$attachments a + join mon$statements s + using (mon$attachment_id) + where + a.mon$attachment_id <> current_connection + and cast(s.mon$sql_text as varchar(8192)) containing '/* A */' + """ + + found_in_mon_tables = False + with act.db.connect() as con_watcher: + + custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) + tx_watcher = con_watcher.transaction_manager(custom_tpb) + cur_watcher = tx_watcher.cursor() + + ps = cur_watcher.prepare(chk_mon_sql) + + i = 0 + da = dt.now() + while True: + cur_watcher.execute(ps) + mon_result = -1 + for r in cur_watcher: + mon_result = r[0] + + tx_watcher.commit() + db = dt.now() + diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 + if mon_result == 1: + found_in_mon_tables = True + break + elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: + break + + time.sleep(0.1) + + ps.free() + + assert found_in_mon_tables, f'Could not find attachment in mon$ tables for {MAX_WAIT_FOR_ISQL_PID_APPEARS_MS} ms.' + + try: + ############################################## + ### f u l l s h u t d o w n D B ### + ############################################## + srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + finally: + p_work_sql.terminate() + # < with open(tmp_log,'w') as f_log + + srv.database.bring_online(database=act.db.db_path) + + trace_options = \ + [ + 'time_threshold = 0' + ,'log_initfini = false' + ,'log_connections = true' + ,'log_transactions = true' + ,'log_errors = true' + ,'log_sweep = true' + ] + + with act.trace(db_events = trace_options, encoding='utf8', encoding_errors='utf8'): + with act.db.connect() as con_for_sweep_start: + time.sleep(2) + + + for line in act.trace_log: + if WATCH_FOR_PTN.search(line): + print(WATCH_FOR_PTN.search(line).group()) + + act.expected_stdout = """ + (ATT_N, , NONE, ) + (ATT_N, , NONE, ) + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From f537764866efefdf94d529b0219a0055b7234b8e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 7 Nov 2024 16:15:14 +0300 Subject: [PATCH 0243/1064] Added/Updated tests\bugs\core_2668_test.py: reverted wrong changes --- tests/bugs/core_2668_test.py | 244 +++++++++-------------------------- 1 file changed, 61 insertions(+), 183 deletions(-) diff --git a/tests/bugs/core_2668_test.py b/tests/bugs/core_2668_test.py index a812742e..e98a8921 100644 --- a/tests/bugs/core_2668_test.py +++ b/tests/bugs/core_2668_test.py @@ -5,214 +5,92 @@ ISSUE: 3072 TITLE: Write note into log when automatic sweep is started DESCRIPTION: - Test changes sweep interval to some low value (see SWEEP_GAP) and runs TX_COUNT transactions which - lead difference between OST and OIT to exceed given sweep interval. These transactions are performed - by ISQL which is launched as child process. SQL script uses table with record that is locked at the - beginning of script and execute block with loop of TX_COUNT statements which insert new records. - After this loop finish, we make ISQL to hang by forcing it to update first record (see LOCKED_ROW). - Then we change DB state to full shutdown and wait until ISQL will be terminated. - At this point database has sweep gap that is enough to run auto sweep at first connection to DB. - Finally, we bring DB online and start trace with log_sweep = true and log_transactions = true. - Doing connection and wait about 2..3 seconds cause auto sweep to be started and completed. - This must be reflected in the trace. - - If ServerMode = 'Super' and ParallelWorkers >= 2 and MaxParallelWorkers >= ParallelWorkers - then trace log will contain folloing five lines related to worker(s) activity: - (...) START_TRANSACTION - (ATT_..., , NONE, ) --------------------- [ 1 ] - (TRA_..., READ_COMMITTED | REC_VERSION | WAIT | READ_ONLY) - (...) COMMIT_TRANSACTION - (ATT_..., , NONE, ) --------------------- [ 2 ] - - This is the only difference that can be observed for snapshots before and after fix - (i.e. BEFORE fix trace had no such lines but all other data about sweep *did* present). - Test checks that trace log contains TWO lines with '', see above [ 1 ] and [ 2 ]. - JIRA: CORE-2668 FBTEST: bugs.core_2668 -NOTES: - [07.11.2024] pzotov - Confirmed absense of lines marked as ',\s+NONE,\s+\)', re.IGNORECASE) -################ - -tmp_sql = temp_file('tmp_2668.sql') -tmp_log = temp_file('tmp_2668.log') -@pytest.mark.es_eds -@pytest.mark.version('>=5.0.0') -def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): - - if act.vars['server-arch'] != 'SuperServer': - pytest.skip("Applies only to SuperServer") +act = python_act('db') - with act.db.connect() as con: - cur = con.cursor() - sql = """ - select - cast(max(iif(g.rdb$config_name = 'ParallelWorkers', g.rdb$config_value, null)) as int) as cfg_par_workers - ,cast(max(iif(g.rdb$config_name = 'MaxParallelWorkers', g.rdb$config_value, null)) as int) as cfg_max_par_workers - from rdb$database - left join rdb$config g on g.rdb$config_name in ('ParallelWorkers', 'MaxParallelWorkers') - """ - cur.execute(sql) - cfg_par_workers, cfg_max_par_workers = cur.fetchone() +test_script = """ +recreate table test(s varchar(36) unique); +insert into test(s) values('LOCKED_FOR_PAUSE'); +commit; - assert cfg_par_workers >=2 and cfg_max_par_workers >= cfg_par_workers, "Server must be configured for parallel work. Check values of ParallelWorkers and MaxParallelWorkers" +set transaction read committed WAIT; - test_script = f""" - set echo on; - set bail on; - connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; +update test set s = s where s = 'LOCKED_FOR_PAUSE'; - recreate table test(id int primary key); - insert into test(id) values({LOCKED_ROW}); - commit; +set term ^; +execute block as + declare n int = 150; + declare v_role varchar(31); +begin + while (n > 0) do + in autonomous transaction do + insert into test(s) values( rpad('', 36, uuid_to_char(gen_uuid()) ) ) + returning :n-1 into n; - set transaction read committed WAIT; + v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); - update test set id = id where id = {LOCKED_ROW}; - set term ^; - execute block as - declare n int = {TX_COUNT}; - declare v_role varchar(31); + begin + execute statement ('update test set s = s where s = ?') ('LOCKED_FOR_PAUSE') + on external + 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user 'SYSDBA' password 'masterkey' role v_role + with autonomous transaction; + when any do begin - while (n > 0) do - in autonomous transaction do - insert into test(id) values(:n) - returning :n-1 into n; + end + end - v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31); +end +^ +set term ;^ +set heading off; +select '-- shutdown me now --' from rdb$database; +""" - begin - execute statement ('update test /* ' || ascii_char(65) || ' */ set id = id where id = ?') ({LOCKED_ROW}) - on external - 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user '{act.db.user}' password '{act.db.password}' role v_role - with autonomous transaction; - when any do - begin - end - end +tmp_script = temp_file('work_script.sql') - end - ^ - set term ;^ - set heading off; - select '-- shutdown me now --' from rdb$database; - """ - - tmp_sql.write_text(test_script) +@pytest.mark.es_eds +@pytest.mark.version('>=3') +def test_1(act: Action, tmp_script: Path): + tmp_script.write_text(test_script) with act.connect_server() as srv: - ############################## - ### reduce SWEEEP interval ### - ############################## - srv.database.set_sweep_interval(database = act.db.db_path, interval = SWEEP_GAP) + srv.database.set_sweep_interval(database=act.db.db_path, interval=100) srv.database.set_write_mode(database=act.db.db_path, mode=DbWriteMode.ASYNC) - - with open(tmp_log,'w') as f_log: - p_work_sql = subprocess.Popen([act.vars['isql'], '-q', '-i', str(tmp_sql)], stdout = f_log, stderr = subprocess.STDOUT) - - chk_mon_sql = """ - select 1 - from mon$attachments a - join mon$statements s - using (mon$attachment_id) - where - a.mon$attachment_id <> current_connection - and cast(s.mon$sql_text as varchar(8192)) containing '/* A */' - """ - - found_in_mon_tables = False - with act.db.connect() as con_watcher: - - custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) - tx_watcher = con_watcher.transaction_manager(custom_tpb) - cur_watcher = tx_watcher.cursor() - - ps = cur_watcher.prepare(chk_mon_sql) - - i = 0 - da = dt.now() - while True: - cur_watcher.execute(ps) - mon_result = -1 - for r in cur_watcher: - mon_result = r[0] - - tx_watcher.commit() - db = dt.now() - diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 - if mon_result == 1: - found_in_mon_tables = True - break - elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: - break - - time.sleep(0.1) - - ps.free() - - assert found_in_mon_tables, f'Could not find attachment in mon$ tables for {MAX_WAIT_FOR_ISQL_PID_APPEARS_MS} ms.' - - try: - ############################################## - ### f u l l s h u t d o w n D B ### - ############################################## - srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, - method=ShutdownMethod.FORCED, timeout=0) - finally: - p_work_sql.terminate() - # < with open(tmp_log,'w') as f_log - + p_work_sql = subprocess.Popen([act.vars['isql'], '-i', str(tmp_script), + '-user', act.db.user, + '-password', act.db.password, act.db.dsn], + stderr = subprocess.STDOUT) + time.sleep(3) + try: + srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + finally: + p_work_sql.terminate() srv.database.bring_online(database=act.db.db_path) - - trace_options = \ - [ - 'time_threshold = 0' - ,'log_initfini = false' - ,'log_connections = true' - ,'log_transactions = true' - ,'log_errors = true' - ,'log_sweep = true' - ] - - with act.trace(db_events = trace_options, encoding='utf8', encoding_errors='utf8'): + srv.info.get_log() + fblog_before = srv.readlines() with act.db.connect() as con_for_sweep_start: + con_for_sweep_start.begin() time.sleep(2) - - - for line in act.trace_log: - if WATCH_FOR_PTN.search(line): - print(WATCH_FOR_PTN.search(line).group()) - - act.expected_stdout = """ - (ATT_N, , NONE, ) - (ATT_N, , NONE, ) - """ - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout + srv.info.get_log() + fblog_after = srv.readlines() + pattern = re.compile('Sweep\\s+.*SWEEPER', re.IGNORECASE) + success = False + for line in unified_diff(fblog_before, fblog_after): + if line.startswith('+') and pattern.search(line): + success = True + assert success From 27486062b94eb964f2c67200673a011f11ee0df4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 8 Nov 2024 10:19:22 +0300 Subject: [PATCH 0244/1064] Added/Updated tests\bugs\core_5381_test.py: Reimplemented - see notes. Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1553, 6.0.0.520 --- tests/bugs/core_5381_test.py | 2059 ++++++++++++++++++++++++++++++++-- 1 file changed, 1987 insertions(+), 72 deletions(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index 0577b6d5..f085b286 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -2,104 +2,2019 @@ """ ID: issue-5654 -ISSUE: 5654 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5654 TITLE: Regression: could not execute query (select from view with nested view) DESCRIPTION: + Test uses queries from ticket but creates user tables instead of rdb$ ones. + We ask FB to show explained plan for query. + Before fix this caused to '335544382 : request size limit exceeded' JIRA: CORE-5381 FBTEST: bugs.core_5381 +NOTES: + [08.11.2024] pzotov + + Re-implemented. No sense to check execution time. Only explained plan must be verified. + + Confirmed bug on 3.0.1.32609 (27-sep-2016), got in trace: + 2024-11-08T00:42:49.8710 ERROR AT JStatement::prepare + 335544382 : request size limit exceeded + + 2024-11-08T00:42:49.8710 FAILED EXECUTE_STATEMENT_FINISH + ... + 0 records fetched + 135383 ms + + Checked 3.0.2.32659 (06-jan-2017), got: + 2024-11-08T00:39:40.0380 EXECUTE_STATEMENT_FINISH + 0 records fetched + 2 ms, 11 read(s), 3763 fetch(es) + ... + Table statistics same for 3.x ... 6.x. + + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1553, 6.0.0.520 """ import pytest from firebird.qa import * +from firebird.driver import DatabaseError + +init_sql = """ + create or alter procedure sp_test as begin end; + recreate view test_view as select 1 x from rdb$database; + recreate view inner_view as select 1 x from rdb$database; + + recreate table rdb_types( + id int generated by default as identity constraint pk_rdb_types primary key + ,type_id int + ); -db = db_factory() + recreate table rdb_rels( + id int generated by default as identity constraint pk_rdb_rels primary key + ,rel_id int + ); -test_script = """ - create table t1(ID bigint not null primary key); - create table t2(ID bigint not null primary key); - create table t3(ID bigint not null primary key); - create table t4(ID bigint not null primary key); - create table t5(ID bigint not null primary key); - create table t6(ID bigint not null primary key); - create table t7(ID bigint not null primary key); - create table t8(ID bigint not null primary key); + recreate table rdb_deps( + id int generated by default as identity constraint pk_rdb_deps primary key + ,dep_type int + ); - create view inner_view(ID) + recreate table rdb_colls( + id int generated by default as identity constraint pk_rdb_colls primary key + ,coll_id int + ); + + recreate table rdb_flds( + id int generated by default as identity constraint pk_rdb_flds primary key + ,fld_type_id int + ); + + recreate table rdb_csets( + id int generated by default as identity constraint pk_rdb_csets primary key + ,cset_id int + ); + + + recreate table t1(id bigint not null primary key using index pk_t1_id); + recreate table t2(id bigint not null primary key using index pk_t2_id); + recreate table t3(id bigint not null primary key using index pk_t3_id); + recreate table t4(id bigint not null primary key using index pk_t4_id); + recreate table t5(id bigint not null primary key using index pk_t5_id); + recreate table t6(id bigint not null primary key using index pk_t6_id); + recreate table t7(id bigint not null primary key using index pk_t7_id); + recreate table t8(id bigint not null primary key using index pk_t8_id); + + recreate view inner_view as - select t1.ID - from t1 - inner join t8 B on B.ID = t1.ID - inner join t2 C on C.ID = t1.ID - left join t4 D on D.ID = t1.ID - inner join t5 E on E.ID = t1.ID - left join t6 F on F.ID = t1.ID - - inner join RDB$TYPES G1 on G1.rdb$type = t1.ID - inner join RDB$RELATIONS G2 on G2.rdb$relation_id = t1.ID - inner join RDB$DEPENDENCIES G3 on G3.rdb$dependent_type = t1.ID - inner join RDB$COLLATIONS G4 on G4.rdb$collation_id = t1.ID - inner join RDB$FIELDS G5 on G5.rdb$field_type = t1.ID - inner join RDB$CHARACTER_SETS G6 on G6.rdb$character_set_id = t1.ID + select t1.id + from t1 + inner join t8 b on b.id = t1.id + inner join t2 c on c.id = t1.id + left join t4 d on d.id = t1.id + inner join t5 e on e.id = t1.id + left join t6 f on f.id = t1.id + + inner join rdb_types g1 on g1.type_id = t1.id + inner join rdb_rels g2 on g2.rel_id = t1.id + inner join rdb_deps g3 on g3.dep_type = t1.id + inner join rdb_colls g4 on g4.coll_id = t1.id + inner join rdb_flds g5 on g5.fld_type_id = t1.id + inner join rdb_csets g6 on g6.cset_id = t1.id ; - create view test_view(ID) + recreate view test_view as - select t1.ID - from t1 - inner join inner_view on inner_view.ID = t1.ID - inner join t7 on t7.ID = t1.ID - left join t3 on t3.ID = t1.ID - - inner join RDB$TYPES D1 on D1.rdb$type = t1.ID - inner join RDB$RELATIONS D2 on D2.rdb$relation_id = t1.ID - inner join RDB$DEPENDENCIES D3 on D3.rdb$dependent_type = t1.ID - inner join RDB$COLLATIONS D4 on D4.rdb$collation_id = t1.ID - inner join RDB$FIELDS D5 on D5.rdb$field_type = t1.ID - ; - commit; + select t1.id + from t1 + inner join inner_view on inner_view.id = t1.id + inner join t7 on t7.id = t1.id + left join t3 on t3.id = t1.id - set list on; + inner join rdb_types d1 on d1.type_id = t1.id + inner join rdb_rels d2 on d2.rel_id = t1.id + inner join rdb_deps d3 on d3.dep_type = t1.id + inner join rdb_colls d4 on d4.coll_id = t1.id + inner join rdb_flds d5 on d5.fld_type_id = t1.id + ; set term ^; - execute block returns( result varchar(128) ) as - declare dts_beg timestamp; + create or alter procedure sp_test as declare c int; - declare elap_ms int; - declare max_allowed_ms int = 1000; - -- ##### - -- ^ - -- | - -- ########################### - -- ### T H R E S H O L D ### - -- ########################### begin - dts_beg ='now'; - - select A.ID - from test_view A - inner join RDB$TYPES D1 on D1.rdb$type = A.ID - inner join RDB$RELATIONS D2 on D2.rdb$relation_id = A.ID - inner join RDB$DEPENDENCIES D3 on D3.rdb$dependent_type = A.ID - where A.ID = 1 - into c; - elap_ms = datediff(millisecond from dts_beg to cast('now' as timestamp)); - result = iif(elap_ms <= max_allowed_ms, 'Acceptable.', 'TOO LONG: ' || elap_ms || ' ms - more than max allowed ' || max_allowed_ms || ' ms.' ); - suspend; + for execute statement + 'select a.id + from test_view a + inner join rdb_types d1 on d1.type_id = a.id + inner join rdb_rels d2 on d2.rel_id = a.id + inner join rdb_deps d3 on d3.dep_type = a.id + where a.id = 1' + into c + do begin + -- nop -- + end end ^ set term ;^ + commit; + + insert into t1(id) values(1); + insert into t2(id) select id from t1; + insert into t3(id) select id from t1; + insert into t4(id) select id from t1; + insert into t5(id) select id from t1; + insert into t6(id) select id from t1; + insert into t7(id) select id from t1; + insert into t8(id) select id from t1; + + insert into rdb_csets (cset_id) values (0); + insert into rdb_csets (cset_id) values (1); + insert into rdb_csets (cset_id) values (2); + insert into rdb_csets (cset_id) values (3); + insert into rdb_csets (cset_id) values (4); + insert into rdb_csets (cset_id) values (5); + insert into rdb_csets (cset_id) values (6); + insert into rdb_csets (cset_id) values (10); + insert into rdb_csets (cset_id) values (11); + insert into rdb_csets (cset_id) values (12); + insert into rdb_csets (cset_id) values (21); + insert into rdb_csets (cset_id) values (22); + insert into rdb_csets (cset_id) values (23); + insert into rdb_csets (cset_id) values (34); + insert into rdb_csets (cset_id) values (35); + insert into rdb_csets (cset_id) values (36); + insert into rdb_csets (cset_id) values (37); + insert into rdb_csets (cset_id) values (38); + insert into rdb_csets (cset_id) values (39); + insert into rdb_csets (cset_id) values (40); + insert into rdb_csets (cset_id) values (45); + insert into rdb_csets (cset_id) values (46); + insert into rdb_csets (cset_id) values (13); + insert into rdb_csets (cset_id) values (47); + insert into rdb_csets (cset_id) values (14); + insert into rdb_csets (cset_id) values (50); + insert into rdb_csets (cset_id) values (9); + insert into rdb_csets (cset_id) values (15); + insert into rdb_csets (cset_id) values (16); + insert into rdb_csets (cset_id) values (17); + insert into rdb_csets (cset_id) values (18); + insert into rdb_csets (cset_id) values (48); + insert into rdb_csets (cset_id) values (49); + insert into rdb_csets (cset_id) values (51); + insert into rdb_csets (cset_id) values (52); + insert into rdb_csets (cset_id) values (53); + insert into rdb_csets (cset_id) values (54); + insert into rdb_csets (cset_id) values (55); + insert into rdb_csets (cset_id) values (19); + insert into rdb_csets (cset_id) values (58); + insert into rdb_csets (cset_id) values (59); + insert into rdb_csets (cset_id) values (60); + insert into rdb_csets (cset_id) values (44); + insert into rdb_csets (cset_id) values (56); + insert into rdb_csets (cset_id) values (57); + insert into rdb_csets (cset_id) values (63); + insert into rdb_csets (cset_id) values (64); + insert into rdb_csets (cset_id) values (65); + insert into rdb_csets (cset_id) values (66); + insert into rdb_csets (cset_id) values (67); + insert into rdb_csets (cset_id) values (68); + insert into rdb_csets (cset_id) values (69); + + + insert into rdb_rels(rel_id) select row_number()over()-1 from rdb$types rows 50; + + -- insert into rdb_flds (fld_type_id) values (1); + + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (27); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (23); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (261); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (35); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (7); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (14); + insert into rdb_flds (fld_type_id) values (8); + insert into rdb_flds (fld_type_id) values (16); + insert into rdb_flds (fld_type_id) values (37); + insert into rdb_flds (fld_type_id) values (37); + + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (7); + insert into rdb_colls (coll_id) values (8); + insert into rdb_colls (coll_id) values (9); + insert into rdb_colls (coll_id) values (10); + insert into rdb_colls (coll_id) values (11); + insert into rdb_colls (coll_id) values (12); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (7); + insert into rdb_colls (coll_id) values (8); + insert into rdb_colls (coll_id) values (9); + insert into rdb_colls (coll_id) values (10); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (7); + insert into rdb_colls (coll_id) values (8); + insert into rdb_colls (coll_id) values (9); + insert into rdb_colls (coll_id) values (10); + insert into rdb_colls (coll_id) values (11); + insert into rdb_colls (coll_id) values (12); + insert into rdb_colls (coll_id) values (14); + insert into rdb_colls (coll_id) values (15); + insert into rdb_colls (coll_id) values (16); + insert into rdb_colls (coll_id) values (17); + insert into rdb_colls (coll_id) values (18); + insert into rdb_colls (coll_id) values (19); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (7); + insert into rdb_colls (coll_id) values (8); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (7); + insert into rdb_colls (coll_id) values (8); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (6); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (4); + insert into rdb_colls (coll_id) values (5); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (2); + insert into rdb_colls (coll_id) values (3); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); + insert into rdb_colls (coll_id) values (0); + insert into rdb_colls (coll_id) values (1); -""" -act = isql_act('db', test_script) + insert into rdb_deps (dep_type) values (4); + insert into rdb_deps (dep_type) values (4); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (2); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (15); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (1); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (3); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); + insert into rdb_deps (dep_type) values (5); -expected_stdout = """ - RESULT Acceptable. + insert into rdb_types (type_id) values (14); + insert into rdb_types (type_id) values (7); + insert into rdb_types (type_id) values (8); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (10); + insert into rdb_types (type_id) values (27); + insert into rdb_types (type_id) values (35); + insert into rdb_types (type_id) values (37); + insert into rdb_types (type_id) values (261); + insert into rdb_types (type_id) values (40); + insert into rdb_types (type_id) values (45); + insert into rdb_types (type_id) values (12); + insert into rdb_types (type_id) values (13); + insert into rdb_types (type_id) values (16); + insert into rdb_types (type_id) values (23); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (7); + insert into rdb_types (type_id) values (8); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (8192); + insert into rdb_types (type_id) values (8193); + insert into rdb_types (type_id) values (8194); + insert into rdb_types (type_id) values (8195); + insert into rdb_types (type_id) values (8196); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (7); + insert into rdb_types (type_id) values (8); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (10); + insert into rdb_types (type_id) values (11); + insert into rdb_types (type_id) values (12); + insert into rdb_types (type_id) values (13); + insert into rdb_types (type_id) values (14); + insert into rdb_types (type_id) values (15); + insert into rdb_types (type_id) values (16); + insert into rdb_types (type_id) values (17); + insert into rdb_types (type_id) values (18); + insert into rdb_types (type_id) values (19); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (7); + insert into rdb_types (type_id) values (8); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (10); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (0); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (10); + insert into rdb_types (type_id) values (11); + insert into rdb_types (type_id) values (12); + insert into rdb_types (type_id) values (21); + insert into rdb_types (type_id) values (22); + insert into rdb_types (type_id) values (23); + insert into rdb_types (type_id) values (34); + insert into rdb_types (type_id) values (35); + insert into rdb_types (type_id) values (36); + insert into rdb_types (type_id) values (37); + insert into rdb_types (type_id) values (38); + insert into rdb_types (type_id) values (39); + insert into rdb_types (type_id) values (40); + insert into rdb_types (type_id) values (45); + insert into rdb_types (type_id) values (46); + insert into rdb_types (type_id) values (13); + insert into rdb_types (type_id) values (47); + insert into rdb_types (type_id) values (14); + insert into rdb_types (type_id) values (50); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (15); + insert into rdb_types (type_id) values (16); + insert into rdb_types (type_id) values (17); + insert into rdb_types (type_id) values (18); + insert into rdb_types (type_id) values (48); + insert into rdb_types (type_id) values (49); + insert into rdb_types (type_id) values (51); + insert into rdb_types (type_id) values (52); + insert into rdb_types (type_id) values (53); + insert into rdb_types (type_id) values (54); + insert into rdb_types (type_id) values (55); + insert into rdb_types (type_id) values (19); + insert into rdb_types (type_id) values (58); + insert into rdb_types (type_id) values (59); + insert into rdb_types (type_id) values (60); + insert into rdb_types (type_id) values (44); + insert into rdb_types (type_id) values (56); + insert into rdb_types (type_id) values (57); + insert into rdb_types (type_id) values (63); + insert into rdb_types (type_id) values (64); + insert into rdb_types (type_id) values (65); + insert into rdb_types (type_id) values (66); + insert into rdb_types (type_id) values (67); + insert into rdb_types (type_id) values (68); + insert into rdb_types (type_id) values (69); + insert into rdb_types (type_id) values (1); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (2); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (3); + insert into rdb_types (type_id) values (4); + insert into rdb_types (type_id) values (5); + insert into rdb_types (type_id) values (6); + insert into rdb_types (type_id) values (10); + insert into rdb_types (type_id) values (11); + insert into rdb_types (type_id) values (12); + insert into rdb_types (type_id) values (21); + insert into rdb_types (type_id) values (21); + insert into rdb_types (type_id) values (21); + insert into rdb_types (type_id) values (22); + insert into rdb_types (type_id) values (22); + insert into rdb_types (type_id) values (22); + insert into rdb_types (type_id) values (23); + insert into rdb_types (type_id) values (23); + insert into rdb_types (type_id) values (23); + insert into rdb_types (type_id) values (34); + insert into rdb_types (type_id) values (34); + insert into rdb_types (type_id) values (34); + insert into rdb_types (type_id) values (35); + insert into rdb_types (type_id) values (35); + insert into rdb_types (type_id) values (36); + insert into rdb_types (type_id) values (36); + insert into rdb_types (type_id) values (37); + insert into rdb_types (type_id) values (37); + insert into rdb_types (type_id) values (38); + insert into rdb_types (type_id) values (38); + insert into rdb_types (type_id) values (39); + insert into rdb_types (type_id) values (39); + insert into rdb_types (type_id) values (39); + insert into rdb_types (type_id) values (40); + insert into rdb_types (type_id) values (40); + insert into rdb_types (type_id) values (40); + insert into rdb_types (type_id) values (45); + insert into rdb_types (type_id) values (46); + insert into rdb_types (type_id) values (13); + insert into rdb_types (type_id) values (47); + insert into rdb_types (type_id) values (14); + insert into rdb_types (type_id) values (9); + insert into rdb_types (type_id) values (15); + insert into rdb_types (type_id) values (16); + insert into rdb_types (type_id) values (17); + insert into rdb_types (type_id) values (18); + insert into rdb_types (type_id) values (48); + insert into rdb_types (type_id) values (49); + insert into rdb_types (type_id) values (51); + insert into rdb_types (type_id) values (52); + insert into rdb_types (type_id) values (53); + insert into rdb_types (type_id) values (54); + insert into rdb_types (type_id) values (55); + insert into rdb_types (type_id) values (58); + insert into rdb_types (type_id) values (59); + insert into rdb_types (type_id) values (60); + insert into rdb_types (type_id) values (65); + insert into rdb_types (type_id) values (44); + insert into rdb_types (type_id) values (44); + insert into rdb_types (type_id) values (44); + insert into rdb_types (type_id) values (56); + insert into rdb_types (type_id) values (56); + commit; + + set term ^; + execute block as + begin + for + select trim(ri.rdb$index_name) as idx_name + from rdb$indices ri + where ri.rdb$system_flag is distinct from 1 + as cursor c + do begin + execute statement 'set statistics index ' || c.idx_name ; + end + end + ^ + set term ;^ + commit; """ +db = db_factory(init = init_sql) -@pytest.mark.version('>=3.0.2') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout +act = python_act('db') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- +@pytest.mark.version('>=3.0.1') +def test_1(act: Action, capsys): + + test_sql = """ + select count(*) + from test_view a + inner join rdb_types d1 on d1.type_id = a.id + inner join rdb_rels d2 on d2.rel_id = a.id + inner join rdb_deps d3 on d3.dep_type = a.id + where a.id = 1 + ; + """ + + 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( '\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_3x = """ + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (inner) + ................-> Filter + ....................-> Table "RDB_FLDS" as "A D5" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_DEPS" as "D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_DEPS" as "A D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_TYPES" as "D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_TYPES" as "A D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_COLLS" as "A D4" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_RELS" as "D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Filter + ........................-> Table "RDB_RELS" as "A D2" Full Scan + ................-> Record Buffer (record length: 359) + ....................-> Filter + ........................-> Nested Loop Join (outer) + ............................-> Filter + ................................-> Hash Join (inner) + ....................................-> Filter + ........................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Filter + ............................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Filter + ............................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Filter + ............................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Filter + ............................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Filter + ............................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan + ....................................-> Record Buffer (record length: 208) + ........................................-> Nested Loop Join (inner) + ............................................-> Nested Loop Join (outer) + ................................................-> Nested Loop Join (inner) + ....................................................-> Nested Loop Join (outer) + ........................................................-> Nested Loop Join (inner) + ............................................................-> Filter + ................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T1_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T8_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T2_ID" Unique Scan + ........................................................-> Filter + ............................................................-> Table "T4" as "A INNER_VIEW D" Access By ID + ................................................................-> Bitmap + ....................................................................-> Index "PK_T4_ID" Unique Scan + ....................................................-> Filter + ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID + ............................................................-> Bitmap + ................................................................-> Index "PK_T5_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T6_ID" Unique Scan + ............................................-> Nested Loop Join (inner) + ................................................-> Filter + ....................................................-> Table "T1" as "A T1" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T1_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T7" as "A T7" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T7_ID" Unique Scan + ............................-> Filter + ................................-> Table "T3" as "A T3" Access By ID + ....................................-> Bitmap + ........................................-> Index "PK_T3_ID" Unique Scan + """ + + expected_stdout_4x = """ + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (inner) + ................-> Table "RDB_FLDS" as "A D5" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "A D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_COLLS" as "A D4" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "A D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "A D2" Full Scan + ................-> Record Buffer (record length: 359) + ....................-> Filter + ........................-> Nested Loop Join (outer) + ............................-> Filter + ................................-> Hash Join (inner) + ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan + ....................................-> Record Buffer (record length: 208) + ........................................-> Nested Loop Join (inner) + ............................................-> Nested Loop Join (outer) + ................................................-> Nested Loop Join (inner) + ....................................................-> Nested Loop Join (outer) + ........................................................-> Nested Loop Join (inner) + ............................................................-> Filter + ................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T1_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T8_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T2_ID" Unique Scan + ........................................................-> Filter + ............................................................-> Table "T4" as "A INNER_VIEW D" Access By ID + ................................................................-> Bitmap + ....................................................................-> Index "PK_T4_ID" Unique Scan + ....................................................-> Filter + ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID + ............................................................-> Bitmap + ................................................................-> Index "PK_T5_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T6_ID" Unique Scan + ............................................-> Nested Loop Join (inner) + ................................................-> Filter + ....................................................-> Table "T1" as "A T1" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T1_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T7" as "A T7" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T7_ID" Unique Scan + ............................-> Filter + ................................-> Table "T3" as "A T3" Access By ID + ....................................-> Bitmap + ........................................-> Index "PK_T3_ID" Unique Scan + """ + + expected_stdout_5x = """ + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (inner) + ................-> Table "RDB_FLDS" as "A D5" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "A D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "A D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_COLLS" as "A D4" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "A D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "D3" Full Scan + ................-> Record Buffer (record length: 359) + ....................-> Filter + ........................-> Nested Loop Join (outer) + ............................-> Filter + ................................-> Hash Join (inner) + ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan + ....................................-> Record Buffer (record length: 208) + ........................................-> Nested Loop Join (inner) + ............................................-> Nested Loop Join (outer) + ................................................-> Nested Loop Join (inner) + ....................................................-> Filter + ........................................................-> Nested Loop Join (outer) + ............................................................-> Nested Loop Join (inner) + ................................................................-> Filter + ....................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T1_ID" Unique Scan + ................................................................-> Filter + ....................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T8_ID" Unique Scan + ................................................................-> Filter + ....................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T2_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T4" as "A INNER_VIEW D" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T4_ID" Unique Scan + ....................................................-> Filter + ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID + ............................................................-> Bitmap + ................................................................-> Index "PK_T5_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T6_ID" Unique Scan + ............................................-> Nested Loop Join (inner) + ................................................-> Filter + ....................................................-> Table "T1" as "A T1" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T1_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T7" as "A T7" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T7_ID" Unique Scan + ............................-> Filter + ................................-> Table "T3" as "A T3" Access By ID + ....................................-> Bitmap + ........................................-> Index "PK_T3_ID" Unique Scan + """ + + expected_stdout_6x = """ + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Hash Join (inner) (keys: 1, total key length: 8) + ................-> Table "RDB_FLDS" as "A D5" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "A D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_RELS" as "D2" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "A D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_COLLS" as "A D4" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_TYPES" as "D1" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "A D3" Full Scan + ................-> Record Buffer (record length: 25) + ....................-> Table "RDB_DEPS" as "D3" Full Scan + ................-> Record Buffer (record length: 359) + ....................-> Filter + ........................-> Nested Loop Join (outer) + ............................-> Filter + ................................-> Hash Join (inner) (keys: 1, total key length: 8) + ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan + ....................................-> Record Buffer (record length: 25) + ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan + ....................................-> Record Buffer (record length: 208) + ........................................-> Nested Loop Join (inner) + ............................................-> Nested Loop Join (outer) + ................................................-> Nested Loop Join (inner) + ....................................................-> Filter + ........................................................-> Nested Loop Join (outer) + ............................................................-> Nested Loop Join (inner) + ................................................................-> Filter + ....................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T1_ID" Unique Scan + ................................................................-> Filter + ....................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T8_ID" Unique Scan + ................................................................-> Filter + ....................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID + ........................................................................-> Bitmap + ............................................................................-> Index "PK_T2_ID" Unique Scan + ............................................................-> Filter + ................................................................-> Table "T4" as "A INNER_VIEW D" Access By ID + ....................................................................-> Bitmap + ........................................................................-> Index "PK_T4_ID" Unique Scan + ....................................................-> Filter + ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID + ............................................................-> Bitmap + ................................................................-> Index "PK_T5_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T6_ID" Unique Scan + ............................................-> Nested Loop Join (inner) + ................................................-> Filter + ....................................................-> Table "T1" as "A T1" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T1_ID" Unique Scan + ................................................-> Filter + ....................................................-> Table "T7" as "A T7" Access By ID + ........................................................-> Bitmap + ............................................................-> Index "PK_T7_ID" Unique Scan + ............................-> Filter + ................................-> Table "T3" as "A T3" Access By ID + ....................................-> Bitmap + ........................................-> Index "PK_T3_ID" Unique Scan + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_4x if act.is_version('<5') else 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 From a8f00de4fb47daa11ed167faeb9046150b34da0a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 9 Nov 2024 15:49:01 +0300 Subject: [PATCH 0245/1064] Added/Updated tests\bugs\gh_5537_test.py: Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1553, 6.0.0.520 --- tests/bugs/gh_5537_test.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/bugs/gh_5537_test.py diff --git a/tests/bugs/gh_5537_test.py b/tests/bugs/gh_5537_test.py new file mode 100644 index 00000000..114b1ed9 --- /dev/null +++ b/tests/bugs/gh_5537_test.py @@ -0,0 +1,38 @@ +#coding:utf-8 + +""" +ID: issue-5537 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5537 +TITLE: Non US-ASCII field names treated as unicode, although charset non-unicode, lowering max field length [CORE5258] +DESCRIPTION: +NOTES: + [09.11.2024] pzotov + FB-3.x must raise "Name longer than database column size", all others must work fine. + Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1553, 6.0.0.520 +""" +from pathlib import Path +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db', substitutions = [(r'After line \d+ .*', '')]) +tmp_file = temp_file('tmp_5537.sql') + +@pytest.mark.intl +@pytest.mark.version('>=3') +def test_1(act: Action, tmp_file: Path): + + NON_ASCII_TXT = 'Поле в 26 символов!' + tmp_file.write_bytes(f"""set list on; select '' as "{NON_ASCII_TXT}" from rdb$database;""".encode('cp1251')) + + expected_3x = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Name longer than database column size + """ + expected_4x = f"{NON_ASCII_TXT}" + + act.expected_stdout = expected_3x if act.is_version('<4') else expected_4x + act.isql(switches = ['-q'], input_file = tmp_file, charset = 'win1251', io_enc = 'cp1251', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a4e323c2123e8598d37644f1ab8f7b1fb942a90d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 10 Nov 2024 12:57:50 +0300 Subject: [PATCH 0246/1064] Added/Updated tests\bugs\core_5381_test.py: changed expected output for 4.x: adjusted INDENTATION. --- tests/bugs/core_5381_test.py | 42 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index f085b286..d56058c6 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -1774,37 +1774,51 @@ def test_1(act: Action, capsys): ....-> Aggregate ........-> Filter ............-> Hash Join (inner) - ................-> Table "RDB_FLDS" as "A D5" Full Scan + ................-> Filter + ....................-> Table "RDB_FLDS" as "A D5" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "D3" Full Scan + ....................-> Filter + ........................-> Table "RDB_DEPS" as "D3" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "A D3" Full Scan + ....................-> Filter + ........................-> Table "RDB_DEPS" as "A D3" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "D1" Full Scan + ....................-> Filter + ........................-> Table "RDB_TYPES" as "D1" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_COLLS" as "A D4" Full Scan + ....................-> Filter + ........................-> Table "RDB_COLLS" as "A D4" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "A D1" Full Scan + ....................-> Filter + ........................-> Table "RDB_TYPES" as "A D1" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "D2" Full Scan + ....................-> Filter + ........................-> Table "RDB_RELS" as "D2" Full Scan ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "A D2" Full Scan + ....................-> Filter + ........................-> Table "RDB_RELS" as "A D2" Full Scan ................-> Record Buffer (record length: 359) ....................-> Filter ........................-> Nested Loop Join (outer) ............................-> Filter ................................-> Hash Join (inner) - ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan + ....................................-> Filter + ........................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan + ........................................-> Filter + ............................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan + ........................................-> Filter + ............................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan + ........................................-> Filter + ............................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan + ........................................-> Filter + ............................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan + ........................................-> Filter + ............................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan ....................................-> Record Buffer (record length: 208) ........................................-> Nested Loop Join (inner) ............................................-> Nested Loop Join (outer) From e4df62936a49c66c4d8b8549a5935691cd212db2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 10 Nov 2024 15:37:21 +0300 Subject: [PATCH 0247/1064] Added/Updated tests\bugs\core_5381_test.py: Adjusted notes about changed FB 4.x --- tests/bugs/core_5381_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index d56058c6..710dbc29 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -31,7 +31,24 @@ ... Table statistics same for 3.x ... 6.x. - Checked on 3.0.13.33794, 4.0.6.3165, 5.0.2.1553, 6.0.0.520 + [10.11.2024] pzotov + Explained plan in FB 4.x changed since 4.0.6.3168: + Was: + -> Hash Join (inner) + -> Table "RDB_FLDS" as "A D5" Full Scan + -> Record Buffer (record length: 25) + -> Table "RDB_DEPS" as "D3" Full Scan + ... + Now: + -> Hash Join (inner) + -> Filter + -> Table "RDB_FLDS" as "A D5" Full Scan + -> Record Buffer (record length: 25) + -> Filter + -> Table "RDB_DEPS" as "D3" Full Scan + ... + + Checked on 3.0.13.33794, 4.0.6.3168, 5.0.2.1553, 6.0.0.520 """ import pytest From 6ed135d077f5521c161915b5e238bd0942af57bc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 10 Nov 2024 16:02:38 +0300 Subject: [PATCH 0248/1064] Added/Updated tests\bugs\gh_8309_test.py: Checked on 6.0.0.523-8ca2314. --- tests/bugs/gh_8309_test.py | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/bugs/gh_8309_test.py diff --git a/tests/bugs/gh_8309_test.py b/tests/bugs/gh_8309_test.py new file mode 100644 index 00000000..ac456856 --- /dev/null +++ b/tests/bugs/gh_8309_test.py @@ -0,0 +1,90 @@ +#coding:utf-8 + +""" +ID: issue-8309 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8309 +TITLE: Add ALTER PACKAGE BODY and CRAETE OR ALTER PACKAGE BODY parse rules +DESCRIPTION: + We create package with body. Then we change its body two times: + * using 'ALTER PACKAGE'; + * using 'CREATE OR ALTER PACKAGE' clause. + Both changes must complete without error. +NOTES: + [10.11.2024] pzotov + Checked on 6.0.0.523-8ca2314. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +act = isql_act('db', substitutions=[('[ \\t]+', ' ')]) + +@pytest.mark.version('>=6.0.0') +def test_1(act: Action): + + msg_map = { + 0: 'Initial' + ,1: 'Changed via "ALTER PACKAGE BODY"' + ,2: 'Changed via "CREATE OR ALTER PACKAGE BODY"' + } + + test_sql = f""" + set term ^; + set heading off + ^ + set bail on + ^ + create or alter package pg_test as + begin + function fn_dummy returns varchar(50); + end + ^ + recreate package body pg_test as + begin + function fn_dummy returns varchar(50) as + begin + return '{msg_map[0]}'; + end + end + ^ + select pg_test.fn_dummy() from rdb$database + ^ + + set bail off + ^ + + -- must NOT fail since 6.0.0.523: + alter package body pg_test as + begin + function fn_dummy returns varchar(50) as + begin + return '{msg_map[1]}'; + end + end + ^ + select pg_test.fn_dummy() from rdb$database + ^ + + -- must NOT fail since 6.0.0.523: + create or alter package body pg_test as + begin + function fn_dummy returns varchar(50) as + begin + return '{msg_map[2]}'; + end + end + ^ + select pg_test.fn_dummy() from rdb$database + ^ + """ + + act.expected_stdout = f""" + {msg_map[0]} + {msg_map[1]} + {msg_map[2]} + """ + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From 8767812ce0560635eee1814b4eef3979461d0c27 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 12 Nov 2024 22:36:03 +0300 Subject: [PATCH 0249/1064] Added/Updated tests\bugs\core_5381_test.py: dummy change in order to force all FB versions to be checked at nearest scheduled job --- tests/bugs/core_5381_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index 710dbc29..a1a6ecf3 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -7,7 +7,7 @@ DESCRIPTION: Test uses queries from ticket but creates user tables instead of rdb$ ones. We ask FB to show explained plan for query. - Before fix this caused to '335544382 : request size limit exceeded' + Before fix this caused to '335544382 : request size limit exceeded'. JIRA: CORE-5381 FBTEST: bugs.core_5381 NOTES: From 8ab4fbb19a308be63cab6aa9b2428ba164d38201 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 14 Nov 2024 02:12:33 +0300 Subject: [PATCH 0250/1064] Added/Updated tests\bugs\core_5381_test.py: dummy change in order to force all FB versions to be checked at nearest scheduled job --- tests/bugs/core_5381_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index a1a6ecf3..710dbc29 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -7,7 +7,7 @@ DESCRIPTION: Test uses queries from ticket but creates user tables instead of rdb$ ones. We ask FB to show explained plan for query. - Before fix this caused to '335544382 : request size limit exceeded'. + Before fix this caused to '335544382 : request size limit exceeded' JIRA: CORE-5381 FBTEST: bugs.core_5381 NOTES: From 95be77a751475907a29a6ab86876fd1110db9133 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 15 Nov 2024 01:01:28 +0300 Subject: [PATCH 0251/1064] Added/Updated tests\bugs\core_5381_test.py: dummy change in order to force all FB versions to be checked at nearest scheduled job --- tests/bugs/core_5381_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index 710dbc29..a1a6ecf3 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -7,7 +7,7 @@ DESCRIPTION: Test uses queries from ticket but creates user tables instead of rdb$ ones. We ask FB to show explained plan for query. - Before fix this caused to '335544382 : request size limit exceeded' + Before fix this caused to '335544382 : request size limit exceeded'. JIRA: CORE-5381 FBTEST: bugs.core_5381 NOTES: From ec113ab75046c44b243dd1dca9fe6e003a5693cb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 16 Nov 2024 13:54:46 +0300 Subject: [PATCH 0252/1064] Updated tests\functional\basic\isql\test_00.py: adjust expected stdout/stderr to current FB version. --- tests/functional/basic/isql/test_00.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/functional/basic/isql/test_00.py b/tests/functional/basic/isql/test_00.py index 095e1441..2b29d7a0 100644 --- a/tests/functional/basic/isql/test_00.py +++ b/tests/functional/basic/isql/test_00.py @@ -17,7 +17,7 @@ help set; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [ ('[ \t]+', ' '), ]) fb3x_checked_stdout = """ Frontend commands: @@ -122,7 +122,7 @@ SHOW [] -- display system information = CHECK, COLLATION, DATABASE, DOMAIN, EXCEPTION, FILTER, FUNCTION, GENERATOR, GRANT, INDEX, PACKAGE, PROCEDURE, ROLE, SQL DIALECT, - SYSTEM, TABLE, TRIGGER, VERSION, USERS, VIEW + SYSTEM, TABLE, TRIGGER, VERSION, USERS, VIEW, WIRE_STATISTICS EXIT -- exit and commit changes QUIT -- exit and roll back changes All commands may be abbreviated to letters in CAPitals @@ -149,6 +149,7 @@ SET TIME -- toggle display of timestamp with DATE values SET TERM -- change statement terminator string SET WIDTH [] -- set/unset print width to for column + SET WIRE_stats -- toggle display of wire (network) statistics All commands may be abbreviated to letters in CAPitals """ From b3bd8f785196516940b98896cb13145184f2c988 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 16 Nov 2024 13:55:56 +0300 Subject: [PATCH 0253/1064] Updated tests\functional\basic\isql\test_autoterm_01.py: adjust expected stdout/stderr to current FB version. --- tests/functional/basic/isql/test_autoterm_01.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/basic/isql/test_autoterm_01.py b/tests/functional/basic/isql/test_autoterm_01.py index 8b383452..46665c1d 100644 --- a/tests/functional/basic/isql/test_autoterm_01.py +++ b/tests/functional/basic/isql/test_autoterm_01.py @@ -57,6 +57,7 @@ def test_1(act: Action): ! Print statistics: OFF Print per-table stats: OFF + Print wire stats: OFF Echo commands: OFF List format: ON Show Row Count: OFF From a438838b7cc51d44b65a91768c05b64847aeb5a3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 16 Nov 2024 13:58:12 +0300 Subject: [PATCH 0254/1064] Adjusted expected output after check on 6.0.0.530. --- tests/functional/basic/isql/test_autoterm_01.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/basic/isql/test_autoterm_01.py b/tests/functional/basic/isql/test_autoterm_01.py index 46665c1d..02d01df8 100644 --- a/tests/functional/basic/isql/test_autoterm_01.py +++ b/tests/functional/basic/isql/test_autoterm_01.py @@ -7,6 +7,7 @@ DESCRIPTION: NOTES: Checked on 6.0.0.139 (intermediate snapshot of 23-nov-2023). + Adjusted expected output after check on 6.0.0.530. """ import pytest From 42fa9a402caeb52d7d8426e06268d56e64be4a73 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 11:40:13 +0300 Subject: [PATCH 0255/1064] Added/Updated tests\bugs\core_5020_test.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. --- tests/bugs/core_5020_test.py | 87 +++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/tests/bugs/core_5020_test.py b/tests/bugs/core_5020_test.py index 154befeb..8f1a84fd 100644 --- a/tests/bugs/core_5020_test.py +++ b/tests/bugs/core_5020_test.py @@ -5,16 +5,25 @@ ISSUE: 5308 TITLE: Regression: ORDER BY clause on compound index may disable usage of other indices DESCRIPTION: + Plan in 3.0.0.32179 (before fix): PLAN (ZF ORDER IXA_FK__ID__KONT_ID) + Fixed in 3.0 since: http://sourceforge.net/p/firebird/code/62570 + Checked on 2.5.5.26952 - plans are the same now. JIRA: CORE-5020 FBTEST: bugs.core_5020 +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 * -db = db_factory() - -test_script = """ +init_sql = """ recreate table zf( id integer not null primary key, kont_id integer not null @@ -76,28 +85,64 @@ create index ixa_fk__id__kont_id on zf(id, kont_id); commit; +""" - set planonly; - select zf.* - from zf - where zf.kont_id=5 - order by zf.id, kont_id; - - -- Plan in 3.0.0.32179 (before fix): PLAN (ZF ORDER IXA_FK__ID__KONT_ID) - -- Fixed in 3.0 since: http://sourceforge.net/p/firebird/code/62570 - -- Checked on 2.5.5.26952 - plans are the same now. +db = db_factory(init = init_sql) +act = python_act('db', substitutions = [(r'record length: \d+, key length: \d+', 'record length: NN, key length: MM')]) -""" +#----------------------------------------------------------- -act = isql_act('db', test_script) +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped -expected_stdout = """ - PLAN (ZF ORDER IXA_FK__ID__KONT_ID INDEX (FK_ZF__K)) -""" +#----------------------------------------------------------- @pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() +def test_1(act: Action, capsys): + test_sql = """ + select zf.* + from zf + where zf.kont_id=5 + order by zf.id, kont_id + """ + + 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( '\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 "ZF" Access By ID + ............-> Index "IXA_FK__ID__KONT_ID" Full Scan + ................-> Bitmap + ....................-> Index "FK_ZF__K" Range Scan (full match) + """ + + expected_stdout_6x = """ + Select Expression + ....-> Sort (record length: 36, key length: 16) + ........-> Filter + ............-> Table "ZF" Access By ID + ................-> Bitmap + ....................-> Index "FK_ZF__K" 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 - From aabe3479b739b858072868dc7a2b0cd308680030 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 12:55:43 +0300 Subject: [PATCH 0256/1064] 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. --- .../optimizer/test_opt_sort_by_index_18.py | 186 +++++++++++------- 1 file changed, 111 insertions(+), 75 deletions(-) diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py index bd1e8d8c..12ff791e 100644 --- a/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py @@ -4,89 +4,125 @@ ID: optimizer.sort-by-index-18 TITLE: ORDER BY ASC using index (single) and WHERE clause DESCRIPTION: - WHERE X = 1 ORDER BY Y - Index for both X and Y should be used when available. + 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 -); - -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 ; ^^ - -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; +init_sql = """ + recreate table table_53 ( + id1 integer, + id2 integer + ); + + 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; + + 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; """ -db = db_factory(init=init_script) - -test_script = """SET PLAN ON; -SELECT - t53.ID2, - t53.ID1 -FROM - Table_53 t53 -WHERE - t53.ID1 = 30 -ORDER BY -t53.ID2 ASC;""" - -act = isql_act('db', test_script) - -expected_stdout = """PLAN (T53 ORDER I_TABLE_53_ID2_ASC INDEX (I_TABLE_53_ID1_ASC)) - - ID2 ID1 -============ ============ - - 0 30 - 1 30 - 2 30 - 3 30 - 4 30 - 5 30 - 6 30 - 7 30 - 8 30 -9 30""" +db = db_factory(init = init_sql) + +act = python_act('db', substitutions = [(r'record length: \d+, key length: \d+', 'record length: NN, key length: MM')]) + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- @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 From 57e95fd7f93c8caeb7a6a791c82fff56b81585e2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 13:29:48 +0300 Subject: [PATCH 0257/1064] Added/Updated tests\bugs\gh_7675_test.py: Removed output of concrete data for checked query. It is enough only to display content of SQLDA (lines with 'sqltype:' and 'name:') and SQLSTATE (if some error occurs). --- tests/bugs/gh_7675_test.py | 156 +++++++++++-------------------------- 1 file changed, 47 insertions(+), 109 deletions(-) diff --git a/tests/bugs/gh_7675_test.py b/tests/bugs/gh_7675_test.py index 6abca3e0..253fc4b5 100644 --- a/tests/bugs/gh_7675_test.py +++ b/tests/bugs/gh_7675_test.py @@ -10,7 +10,13 @@ NOTES: [02.10.2023] pzotov Checked on 6.0.0.65. + + [17.11.2024] pzotov + Removed output of concrete data for checked query. + It is enough only to display content of SQLDA (lines with 'sqltype:' and 'name:') and SQLSTATE (if some error occurs). + Checked on 6.0.0.532. """ +import os import pytest from firebird.qa import * @@ -35,119 +41,51 @@ db = db_factory(init = init_sql) test_script = """ - set list on; - select * - from rdb$sql.explain( - q'{ - select m2.id, count(*) - from tmain m2 - join tdetl d using(id) - where m2.x > 0 - group by 1 - }' - ) p - order by p.plan_line; + set sqlda_display on; + select p.* + from rdb$sql.explain('select 1 from rdb$database') as p + rows 0 + ; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|sqltype:|name:).)*$',''),('[ \t]+',' ')]) expected_stdout = """ - PLAN_LINE 1 - RECORD_SOURCE_ID 7 - PARENT_RECORD_SOURCE_ID - LEVEL 0 - OBJECT_TYPE - PACKAGE_NAME - OBJECT_NAME - ALIAS - CARDINALITY - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:4 - Select Expression - PLAN_LINE 2 - RECORD_SOURCE_ID 6 - PARENT_RECORD_SOURCE_ID 7 - LEVEL 1 - OBJECT_TYPE - PACKAGE_NAME - OBJECT_NAME - ALIAS - CARDINALITY 0.1000000000000000 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:5 - -> Aggregate - PLAN_LINE 3 - RECORD_SOURCE_ID 5 - PARENT_RECORD_SOURCE_ID 6 - LEVEL 2 - OBJECT_TYPE - PACKAGE_NAME - OBJECT_NAME - ALIAS - CARDINALITY 100.0000000000000 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:6 - -> Nested Loop Join (inner) - PLAN_LINE 4 - RECORD_SOURCE_ID 2 - PARENT_RECORD_SOURCE_ID 5 - LEVEL 3 - OBJECT_TYPE - PACKAGE_NAME - OBJECT_NAME - ALIAS - CARDINALITY 100.0000000000000 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:7 - -> Filter - PLAN_LINE 5 - RECORD_SOURCE_ID 1 - PARENT_RECORD_SOURCE_ID 2 - LEVEL 4 - OBJECT_TYPE 0 - PACKAGE_NAME - OBJECT_NAME TMAIN - ALIAS M2 - CARDINALITY 100.0000000000000 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:8 - -> Table "TMAIN" as "M2" Access By ID - -> Index "TMAIN_PK" Full Scan - -> Bitmap - -> Index "TMAIN_X" Range Scan (lower bound: 1/1) - PLAN_LINE 6 - RECORD_SOURCE_ID 4 - PARENT_RECORD_SOURCE_ID 5 - LEVEL 3 - OBJECT_TYPE - PACKAGE_NAME - OBJECT_NAME - ALIAS - CARDINALITY 1.000000000000000 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:9 - -> Filter - PLAN_LINE 7 - RECORD_SOURCE_ID 3 - PARENT_RECORD_SOURCE_ID 4 - LEVEL 4 - OBJECT_TYPE 0 - PACKAGE_NAME - OBJECT_NAME TDETL - ALIAS D - CARDINALITY 0.9999999999999999 - RECORD_LENGTH - KEY_LENGTH - ACCESS_PATH 0:a - -> Table "TDETL" as "D" Access By ID - -> Bitmap - -> Index "TDETL_PK" Unique Scan + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: PLAN_LINE alias: PLAN_LINE + + 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + : name: RECORD_SOURCE_ID alias: RECORD_SOURCE_ID + + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: PARENT_RECORD_SOURCE_ID alias: PARENT_RECORD_SOURCE_ID + + 04: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: LEVEL alias: LEVEL + + 05: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: OBJECT_TYPE alias: OBJECT_TYPE + + 06: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + : name: PACKAGE_NAME alias: PACKAGE_NAME + + 07: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + : name: OBJECT_NAME alias: OBJECT_NAME + + 08: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + : name: ALIAS alias: ALIAS + + 09: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + : name: CARDINALITY alias: CARDINALITY + + 10: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: RECORD_LENGTH alias: RECORD_LENGTH + + 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: KEY_LENGTH alias: KEY_LENGTH + + 12: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 UTF8 + : name: ACCESS_PATH alias: ACCESS_PATH """ @pytest.mark.version('>=6.0') From 7982277e69af9d22c1410577d3cc8f5369e34e41 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 13:45:49 +0300 Subject: [PATCH 0258/1064] Added/Updated tests\bugs\gh_7921_test.py: 'OPTIMIZE FOR FIRST ROWS' is used for 6.x - suggesed by dimitr, letter 16.11.2024 15:15. Checked on 6.0.0.532; 5.0.2.1567 --- tests/bugs/gh_7921_test.py | 40 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tests/bugs/gh_7921_test.py b/tests/bugs/gh_7921_test.py index ad6b188b..aa87a133 100644 --- a/tests/bugs/gh_7921_test.py +++ b/tests/bugs/gh_7921_test.py @@ -9,6 +9,13 @@ Confirmed problem on 5.0.0.1303. Checked on 6.0.0.180 (intermediate build 18.12.2023). Checked on 5.0.1.1322 after backporting (commit fef5af38, 23.01.2024). + + [17.11.2024] pzotov + Query text was replaced after https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81 + ( Cost-based decision between ORDER and SORT plans (#8316) ): 'OPTIMIZE FOR FIRST ROWS' is used for 6.x + Suggested by dimitr, letter 16.11.2024 15:15 + + Checked on 6.0.0.532; 5.0.2.1567 """ import pytest @@ -182,21 +189,6 @@ db = db_factory(init = init_sql) -query_lst = [ - """ - select - q2_rozl.dyr_id as "dyrekcja" - ,count(*) as "q2_rozl" - from - rozliczenie q2_rozl - where - q2_rozl.okres_numer = '15' - and q2_rozl.dok_rozliczeniowy_id in ('1') - group by - q2_rozl.dyr_id - """, -] - act = python_act('db') #--------------------------------------------------------- @@ -207,6 +199,24 @@ def replace_leading(source, char="."): @pytest.mark.version('>=5.0.1') def test_1(act: Action, capsys): + + OPT_CLAUSE = '' if act.is_version('<6') else 'optimize for first rows' + query_lst = [ + f""" + select + q2_rozl.dyr_id as "dyrekcja" + ,count(*) as "q2_rozl" + from + rozliczenie q2_rozl + where + q2_rozl.okres_numer = '15' + and q2_rozl.dok_rozliczeniowy_id in ('1') + group by + q2_rozl.dyr_id + {OPT_CLAUSE} + """, + ] + with act.db.connect() as con: cur = con.cursor() for q in query_lst: From 5709c6696cbe183cee38f2bdb93033992e54ff68 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 13:51:40 +0300 Subject: [PATCH 0259/1064] Added/Updated tests\functional\arno\optimizer\test_opt_sort_by_index_18.py: 'OPTIMIZE FOR FIRST ROWS' is used for 6.x - suggesed by dimitr, letter 16.11.2024 15:15. Checked on 6.0.0.532; 5.0.2.1567 --- .../optimizer/test_opt_sort_by_index_18.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py b/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py index 12ff791e..befc5a5e 100644 --- a/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py +++ b/tests/functional/arno/optimizer/test_opt_sort_by_index_18.py @@ -9,10 +9,9 @@ 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. + Query text was replaced after https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81 + ( Cost-based decision between ORDER and SORT plans (#8316) ): 'OPTIMIZE FOR FIRST ROWS' is used for 6.x + Suggested by dimitr, letter 16.11.2024 15:15 Checked on 6.0.0.532; 5.0.2.1567; 4.0.6.3168; 3.0.13.33794. """ @@ -72,8 +71,7 @@ def replace_leading(source, char="."): @pytest.mark.version('>=3') 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 = '' + OPT_CLAUSE = '' if act.is_version('<6') else 'optimize for first rows' test_sql = f""" select @@ -84,7 +82,7 @@ def test_1(act: Action, capsys): t53.id1 = 30 order by t53.id2 asc - {opt_clause} + {OPT_CLAUSE} """ with act.db.connect() as con: @@ -115,9 +113,9 @@ def test_1(act: Action, capsys): expected_stdout_6x = """ Select Expression - ....-> Sort (record length: NN, key length: MM) - ........-> Filter - ............-> Table "TABLE_53" as "T53" Access By ID + ....-> 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) """ From fef11868735ef9a096f8191d029cc0237c4a57cd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 17 Nov 2024 15:03:39 +0300 Subject: [PATCH 0260/1064] Added/Updated tests\bugs\core_5381_test.py: Re-implemented. No sense to check execution time or execution plan. We have to ensure only ability of engine to complete prerape_statement. --- tests/bugs/core_5381_test.py | 1927 +--------------------------------- 1 file changed, 8 insertions(+), 1919 deletions(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index a1a6ecf3..8048d7f4 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -5,49 +5,20 @@ ISSUE: https://github.com/FirebirdSQL/firebird/issues/5654 TITLE: Regression: could not execute query (select from view with nested view) DESCRIPTION: - Test uses queries from ticket but creates user tables instead of rdb$ ones. - We ask FB to show explained plan for query. - Before fix this caused to '335544382 : request size limit exceeded'. + Test uses queries from ticket but creates user tables instead of rdb$ ones. We ask FB only to prepare query. + Before fix this query preparation lasted ~130 seconds with raising '335544382 : request size limit exceeded. JIRA: CORE-5381 FBTEST: bugs.core_5381 NOTES: - [08.11.2024] pzotov + [17.11.2024] pzotov - Re-implemented. No sense to check execution time. Only explained plan must be verified. + Re-implemented. No sense to check execution time or execution plan. + We have to ensure only ability of engine to complete prerape_statement. Confirmed bug on 3.0.1.32609 (27-sep-2016), got in trace: 2024-11-08T00:42:49.8710 ERROR AT JStatement::prepare 335544382 : request size limit exceeded - 2024-11-08T00:42:49.8710 FAILED EXECUTE_STATEMENT_FINISH - ... - 0 records fetched - 135383 ms - - Checked 3.0.2.32659 (06-jan-2017), got: - 2024-11-08T00:39:40.0380 EXECUTE_STATEMENT_FINISH - 0 records fetched - 2 ms, 11 read(s), 3763 fetch(es) - ... - Table statistics same for 3.x ... 6.x. - - [10.11.2024] pzotov - Explained plan in FB 4.x changed since 4.0.6.3168: - Was: - -> Hash Join (inner) - -> Table "RDB_FLDS" as "A D5" Full Scan - -> Record Buffer (record length: 25) - -> Table "RDB_DEPS" as "D3" Full Scan - ... - Now: - -> Hash Join (inner) - -> Filter - -> Table "RDB_FLDS" as "A D5" Full Scan - -> Record Buffer (record length: 25) - -> Filter - -> Table "RDB_DEPS" as "D3" Full Scan - ... - Checked on 3.0.13.33794, 4.0.6.3168, 5.0.2.1553, 6.0.0.520 """ @@ -56,7 +27,6 @@ from firebird.driver import DatabaseError init_sql = """ - create or alter procedure sp_test as begin end; recreate view test_view as select 1 x from rdb$database; recreate view inner_view as select 1 x from rdb$database; @@ -100,8 +70,7 @@ recreate table t7(id bigint not null primary key using index pk_t7_id); recreate table t8(id bigint not null primary key using index pk_t8_id); - recreate view inner_view - as + recreate view inner_view as select t1.id from t1 inner join t8 b on b.id = t1.id @@ -109,7 +78,6 @@ left join t4 d on d.id = t1.id inner join t5 e on e.id = t1.id left join t6 f on f.id = t1.id - inner join rdb_types g1 on g1.type_id = t1.id inner join rdb_rels g2 on g2.rel_id = t1.id inner join rdb_deps g3 on g3.dep_type = t1.id @@ -132,1521 +100,6 @@ inner join rdb_colls d4 on d4.coll_id = t1.id inner join rdb_flds d5 on d5.fld_type_id = t1.id ; - - set term ^; - create or alter procedure sp_test as - declare c int; - begin - for execute statement - 'select a.id - from test_view a - inner join rdb_types d1 on d1.type_id = a.id - inner join rdb_rels d2 on d2.rel_id = a.id - inner join rdb_deps d3 on d3.dep_type = a.id - where a.id = 1' - into c - do begin - -- nop -- - end - end - ^ - set term ;^ - commit; - - insert into t1(id) values(1); - insert into t2(id) select id from t1; - insert into t3(id) select id from t1; - insert into t4(id) select id from t1; - insert into t5(id) select id from t1; - insert into t6(id) select id from t1; - insert into t7(id) select id from t1; - insert into t8(id) select id from t1; - - insert into rdb_csets (cset_id) values (0); - insert into rdb_csets (cset_id) values (1); - insert into rdb_csets (cset_id) values (2); - insert into rdb_csets (cset_id) values (3); - insert into rdb_csets (cset_id) values (4); - insert into rdb_csets (cset_id) values (5); - insert into rdb_csets (cset_id) values (6); - insert into rdb_csets (cset_id) values (10); - insert into rdb_csets (cset_id) values (11); - insert into rdb_csets (cset_id) values (12); - insert into rdb_csets (cset_id) values (21); - insert into rdb_csets (cset_id) values (22); - insert into rdb_csets (cset_id) values (23); - insert into rdb_csets (cset_id) values (34); - insert into rdb_csets (cset_id) values (35); - insert into rdb_csets (cset_id) values (36); - insert into rdb_csets (cset_id) values (37); - insert into rdb_csets (cset_id) values (38); - insert into rdb_csets (cset_id) values (39); - insert into rdb_csets (cset_id) values (40); - insert into rdb_csets (cset_id) values (45); - insert into rdb_csets (cset_id) values (46); - insert into rdb_csets (cset_id) values (13); - insert into rdb_csets (cset_id) values (47); - insert into rdb_csets (cset_id) values (14); - insert into rdb_csets (cset_id) values (50); - insert into rdb_csets (cset_id) values (9); - insert into rdb_csets (cset_id) values (15); - insert into rdb_csets (cset_id) values (16); - insert into rdb_csets (cset_id) values (17); - insert into rdb_csets (cset_id) values (18); - insert into rdb_csets (cset_id) values (48); - insert into rdb_csets (cset_id) values (49); - insert into rdb_csets (cset_id) values (51); - insert into rdb_csets (cset_id) values (52); - insert into rdb_csets (cset_id) values (53); - insert into rdb_csets (cset_id) values (54); - insert into rdb_csets (cset_id) values (55); - insert into rdb_csets (cset_id) values (19); - insert into rdb_csets (cset_id) values (58); - insert into rdb_csets (cset_id) values (59); - insert into rdb_csets (cset_id) values (60); - insert into rdb_csets (cset_id) values (44); - insert into rdb_csets (cset_id) values (56); - insert into rdb_csets (cset_id) values (57); - insert into rdb_csets (cset_id) values (63); - insert into rdb_csets (cset_id) values (64); - insert into rdb_csets (cset_id) values (65); - insert into rdb_csets (cset_id) values (66); - insert into rdb_csets (cset_id) values (67); - insert into rdb_csets (cset_id) values (68); - insert into rdb_csets (cset_id) values (69); - - - insert into rdb_rels(rel_id) select row_number()over()-1 from rdb$types rows 50; - - -- insert into rdb_flds (fld_type_id) values (1); - - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (27); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (23); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (261); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (35); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (7); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (14); - insert into rdb_flds (fld_type_id) values (8); - insert into rdb_flds (fld_type_id) values (16); - insert into rdb_flds (fld_type_id) values (37); - insert into rdb_flds (fld_type_id) values (37); - - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (7); - insert into rdb_colls (coll_id) values (8); - insert into rdb_colls (coll_id) values (9); - insert into rdb_colls (coll_id) values (10); - insert into rdb_colls (coll_id) values (11); - insert into rdb_colls (coll_id) values (12); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (7); - insert into rdb_colls (coll_id) values (8); - insert into rdb_colls (coll_id) values (9); - insert into rdb_colls (coll_id) values (10); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (7); - insert into rdb_colls (coll_id) values (8); - insert into rdb_colls (coll_id) values (9); - insert into rdb_colls (coll_id) values (10); - insert into rdb_colls (coll_id) values (11); - insert into rdb_colls (coll_id) values (12); - insert into rdb_colls (coll_id) values (14); - insert into rdb_colls (coll_id) values (15); - insert into rdb_colls (coll_id) values (16); - insert into rdb_colls (coll_id) values (17); - insert into rdb_colls (coll_id) values (18); - insert into rdb_colls (coll_id) values (19); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (7); - insert into rdb_colls (coll_id) values (8); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (7); - insert into rdb_colls (coll_id) values (8); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (6); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (4); - insert into rdb_colls (coll_id) values (5); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (2); - insert into rdb_colls (coll_id) values (3); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - insert into rdb_colls (coll_id) values (0); - insert into rdb_colls (coll_id) values (1); - - - insert into rdb_deps (dep_type) values (4); - insert into rdb_deps (dep_type) values (4); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (2); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (15); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (1); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (3); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - insert into rdb_deps (dep_type) values (5); - - insert into rdb_types (type_id) values (14); - insert into rdb_types (type_id) values (7); - insert into rdb_types (type_id) values (8); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (10); - insert into rdb_types (type_id) values (27); - insert into rdb_types (type_id) values (35); - insert into rdb_types (type_id) values (37); - insert into rdb_types (type_id) values (261); - insert into rdb_types (type_id) values (40); - insert into rdb_types (type_id) values (45); - insert into rdb_types (type_id) values (12); - insert into rdb_types (type_id) values (13); - insert into rdb_types (type_id) values (16); - insert into rdb_types (type_id) values (23); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (7); - insert into rdb_types (type_id) values (8); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (8192); - insert into rdb_types (type_id) values (8193); - insert into rdb_types (type_id) values (8194); - insert into rdb_types (type_id) values (8195); - insert into rdb_types (type_id) values (8196); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (7); - insert into rdb_types (type_id) values (8); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (10); - insert into rdb_types (type_id) values (11); - insert into rdb_types (type_id) values (12); - insert into rdb_types (type_id) values (13); - insert into rdb_types (type_id) values (14); - insert into rdb_types (type_id) values (15); - insert into rdb_types (type_id) values (16); - insert into rdb_types (type_id) values (17); - insert into rdb_types (type_id) values (18); - insert into rdb_types (type_id) values (19); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (7); - insert into rdb_types (type_id) values (8); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (10); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (0); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (10); - insert into rdb_types (type_id) values (11); - insert into rdb_types (type_id) values (12); - insert into rdb_types (type_id) values (21); - insert into rdb_types (type_id) values (22); - insert into rdb_types (type_id) values (23); - insert into rdb_types (type_id) values (34); - insert into rdb_types (type_id) values (35); - insert into rdb_types (type_id) values (36); - insert into rdb_types (type_id) values (37); - insert into rdb_types (type_id) values (38); - insert into rdb_types (type_id) values (39); - insert into rdb_types (type_id) values (40); - insert into rdb_types (type_id) values (45); - insert into rdb_types (type_id) values (46); - insert into rdb_types (type_id) values (13); - insert into rdb_types (type_id) values (47); - insert into rdb_types (type_id) values (14); - insert into rdb_types (type_id) values (50); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (15); - insert into rdb_types (type_id) values (16); - insert into rdb_types (type_id) values (17); - insert into rdb_types (type_id) values (18); - insert into rdb_types (type_id) values (48); - insert into rdb_types (type_id) values (49); - insert into rdb_types (type_id) values (51); - insert into rdb_types (type_id) values (52); - insert into rdb_types (type_id) values (53); - insert into rdb_types (type_id) values (54); - insert into rdb_types (type_id) values (55); - insert into rdb_types (type_id) values (19); - insert into rdb_types (type_id) values (58); - insert into rdb_types (type_id) values (59); - insert into rdb_types (type_id) values (60); - insert into rdb_types (type_id) values (44); - insert into rdb_types (type_id) values (56); - insert into rdb_types (type_id) values (57); - insert into rdb_types (type_id) values (63); - insert into rdb_types (type_id) values (64); - insert into rdb_types (type_id) values (65); - insert into rdb_types (type_id) values (66); - insert into rdb_types (type_id) values (67); - insert into rdb_types (type_id) values (68); - insert into rdb_types (type_id) values (69); - insert into rdb_types (type_id) values (1); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (2); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (3); - insert into rdb_types (type_id) values (4); - insert into rdb_types (type_id) values (5); - insert into rdb_types (type_id) values (6); - insert into rdb_types (type_id) values (10); - insert into rdb_types (type_id) values (11); - insert into rdb_types (type_id) values (12); - insert into rdb_types (type_id) values (21); - insert into rdb_types (type_id) values (21); - insert into rdb_types (type_id) values (21); - insert into rdb_types (type_id) values (22); - insert into rdb_types (type_id) values (22); - insert into rdb_types (type_id) values (22); - insert into rdb_types (type_id) values (23); - insert into rdb_types (type_id) values (23); - insert into rdb_types (type_id) values (23); - insert into rdb_types (type_id) values (34); - insert into rdb_types (type_id) values (34); - insert into rdb_types (type_id) values (34); - insert into rdb_types (type_id) values (35); - insert into rdb_types (type_id) values (35); - insert into rdb_types (type_id) values (36); - insert into rdb_types (type_id) values (36); - insert into rdb_types (type_id) values (37); - insert into rdb_types (type_id) values (37); - insert into rdb_types (type_id) values (38); - insert into rdb_types (type_id) values (38); - insert into rdb_types (type_id) values (39); - insert into rdb_types (type_id) values (39); - insert into rdb_types (type_id) values (39); - insert into rdb_types (type_id) values (40); - insert into rdb_types (type_id) values (40); - insert into rdb_types (type_id) values (40); - insert into rdb_types (type_id) values (45); - insert into rdb_types (type_id) values (46); - insert into rdb_types (type_id) values (13); - insert into rdb_types (type_id) values (47); - insert into rdb_types (type_id) values (14); - insert into rdb_types (type_id) values (9); - insert into rdb_types (type_id) values (15); - insert into rdb_types (type_id) values (16); - insert into rdb_types (type_id) values (17); - insert into rdb_types (type_id) values (18); - insert into rdb_types (type_id) values (48); - insert into rdb_types (type_id) values (49); - insert into rdb_types (type_id) values (51); - insert into rdb_types (type_id) values (52); - insert into rdb_types (type_id) values (53); - insert into rdb_types (type_id) values (54); - insert into rdb_types (type_id) values (55); - insert into rdb_types (type_id) values (58); - insert into rdb_types (type_id) values (59); - insert into rdb_types (type_id) values (60); - insert into rdb_types (type_id) values (65); - insert into rdb_types (type_id) values (44); - insert into rdb_types (type_id) values (44); - insert into rdb_types (type_id) values (44); - insert into rdb_types (type_id) values (56); - insert into rdb_types (type_id) values (56); - commit; - - set term ^; - execute block as - begin - for - select trim(ri.rdb$index_name) as idx_name - from rdb$indices ri - where ri.rdb$system_flag is distinct from 1 - as cursor c - do begin - execute statement 'set statistics index ' || c.idx_name ; - end - end - ^ - set term ;^ commit; """ db = db_factory(init = init_sql) @@ -1655,12 +108,6 @@ #----------------------------------------------------------- -def replace_leading(source, char="."): - stripped = source.lstrip() - return char * (len(source) - len(stripped)) + stripped - -#----------------------------------------------------------- - @pytest.mark.version('>=3.0.1') def test_1(act: Action, capsys): @@ -1679,10 +126,7 @@ def test_1(act: Action, capsys): ps = None try: ps = cur.prepare(test_sql) - - # Print explained plan with padding eash line by dots in order to see indentations: - print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - print('') + print('Completed.') except DatabaseError as e: print(e.__str__()) print(e.gds_codes) @@ -1690,362 +134,7 @@ def test_1(act: Action, capsys): if ps: ps.free() - - expected_stdout_3x = """ - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Hash Join (inner) - ................-> Filter - ....................-> Table "RDB_FLDS" as "A D5" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_DEPS" as "D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_DEPS" as "A D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_TYPES" as "D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_TYPES" as "A D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_COLLS" as "A D4" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_RELS" as "D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_RELS" as "A D2" Full Scan - ................-> Record Buffer (record length: 359) - ....................-> Filter - ........................-> Nested Loop Join (outer) - ............................-> Filter - ................................-> Hash Join (inner) - ....................................-> Filter - ........................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan - ....................................-> Record Buffer (record length: 208) - ........................................-> Nested Loop Join (inner) - ............................................-> Nested Loop Join (outer) - ................................................-> Nested Loop Join (inner) - ....................................................-> Nested Loop Join (outer) - ........................................................-> Nested Loop Join (inner) - ............................................................-> Filter - ................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T1_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T8_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T2_ID" Unique Scan - ........................................................-> Filter - ............................................................-> Table "T4" as "A INNER_VIEW D" Access By ID - ................................................................-> Bitmap - ....................................................................-> Index "PK_T4_ID" Unique Scan - ....................................................-> Filter - ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID - ............................................................-> Bitmap - ................................................................-> Index "PK_T5_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T6_ID" Unique Scan - ............................................-> Nested Loop Join (inner) - ................................................-> Filter - ....................................................-> Table "T1" as "A T1" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T1_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T7" as "A T7" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T7_ID" Unique Scan - ............................-> Filter - ................................-> Table "T3" as "A T3" Access By ID - ....................................-> Bitmap - ........................................-> Index "PK_T3_ID" Unique Scan - """ - - expected_stdout_4x = """ - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Hash Join (inner) - ................-> Filter - ....................-> Table "RDB_FLDS" as "A D5" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_DEPS" as "D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_DEPS" as "A D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_TYPES" as "D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_COLLS" as "A D4" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_TYPES" as "A D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_RELS" as "D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Filter - ........................-> Table "RDB_RELS" as "A D2" Full Scan - ................-> Record Buffer (record length: 359) - ....................-> Filter - ........................-> Nested Loop Join (outer) - ............................-> Filter - ................................-> Hash Join (inner) - ....................................-> Filter - ........................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Filter - ............................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan - ....................................-> Record Buffer (record length: 208) - ........................................-> Nested Loop Join (inner) - ............................................-> Nested Loop Join (outer) - ................................................-> Nested Loop Join (inner) - ....................................................-> Nested Loop Join (outer) - ........................................................-> Nested Loop Join (inner) - ............................................................-> Filter - ................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T1_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T8_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T2_ID" Unique Scan - ........................................................-> Filter - ............................................................-> Table "T4" as "A INNER_VIEW D" Access By ID - ................................................................-> Bitmap - ....................................................................-> Index "PK_T4_ID" Unique Scan - ....................................................-> Filter - ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID - ............................................................-> Bitmap - ................................................................-> Index "PK_T5_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T6_ID" Unique Scan - ............................................-> Nested Loop Join (inner) - ................................................-> Filter - ....................................................-> Table "T1" as "A T1" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T1_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T7" as "A T7" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T7_ID" Unique Scan - ............................-> Filter - ................................-> Table "T3" as "A T3" Access By ID - ....................................-> Bitmap - ........................................-> Index "PK_T3_ID" Unique Scan - """ - - expected_stdout_5x = """ - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Hash Join (inner) - ................-> Table "RDB_FLDS" as "A D5" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "A D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "A D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_COLLS" as "A D4" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "A D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "D3" Full Scan - ................-> Record Buffer (record length: 359) - ....................-> Filter - ........................-> Nested Loop Join (outer) - ............................-> Filter - ................................-> Hash Join (inner) - ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan - ....................................-> Record Buffer (record length: 208) - ........................................-> Nested Loop Join (inner) - ............................................-> Nested Loop Join (outer) - ................................................-> Nested Loop Join (inner) - ....................................................-> Filter - ........................................................-> Nested Loop Join (outer) - ............................................................-> Nested Loop Join (inner) - ................................................................-> Filter - ....................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T1_ID" Unique Scan - ................................................................-> Filter - ....................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T8_ID" Unique Scan - ................................................................-> Filter - ....................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T2_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T4" as "A INNER_VIEW D" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T4_ID" Unique Scan - ....................................................-> Filter - ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID - ............................................................-> Bitmap - ................................................................-> Index "PK_T5_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T6_ID" Unique Scan - ............................................-> Nested Loop Join (inner) - ................................................-> Filter - ....................................................-> Table "T1" as "A T1" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T1_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T7" as "A T7" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T7_ID" Unique Scan - ............................-> Filter - ................................-> Table "T3" as "A T3" Access By ID - ....................................-> Bitmap - ........................................-> Index "PK_T3_ID" Unique Scan - """ - - expected_stdout_6x = """ - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Hash Join (inner) (keys: 1, total key length: 8) - ................-> Table "RDB_FLDS" as "A D5" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "A D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_RELS" as "D2" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "A D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_COLLS" as "A D4" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_TYPES" as "D1" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "A D3" Full Scan - ................-> Record Buffer (record length: 25) - ....................-> Table "RDB_DEPS" as "D3" Full Scan - ................-> Record Buffer (record length: 359) - ....................-> Filter - ........................-> Nested Loop Join (outer) - ............................-> Filter - ................................-> Hash Join (inner) (keys: 1, total key length: 8) - ....................................-> Table "RDB_FLDS" as "A INNER_VIEW G5" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_RELS" as "A INNER_VIEW G2" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_CSETS" as "A INNER_VIEW G6" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_TYPES" as "A INNER_VIEW G1" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_COLLS" as "A INNER_VIEW G4" Full Scan - ....................................-> Record Buffer (record length: 25) - ........................................-> Table "RDB_DEPS" as "A INNER_VIEW G3" Full Scan - ....................................-> Record Buffer (record length: 208) - ........................................-> Nested Loop Join (inner) - ............................................-> Nested Loop Join (outer) - ................................................-> Nested Loop Join (inner) - ....................................................-> Filter - ........................................................-> Nested Loop Join (outer) - ............................................................-> Nested Loop Join (inner) - ................................................................-> Filter - ....................................................................-> Table "T1" as "A INNER_VIEW T1" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T1_ID" Unique Scan - ................................................................-> Filter - ....................................................................-> Table "T8" as "A INNER_VIEW B" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T8_ID" Unique Scan - ................................................................-> Filter - ....................................................................-> Table "T2" as "A INNER_VIEW C" Access By ID - ........................................................................-> Bitmap - ............................................................................-> Index "PK_T2_ID" Unique Scan - ............................................................-> Filter - ................................................................-> Table "T4" as "A INNER_VIEW D" Access By ID - ....................................................................-> Bitmap - ........................................................................-> Index "PK_T4_ID" Unique Scan - ....................................................-> Filter - ........................................................-> Table "T5" as "A INNER_VIEW E" Access By ID - ............................................................-> Bitmap - ................................................................-> Index "PK_T5_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T6" as "A INNER_VIEW F" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T6_ID" Unique Scan - ............................................-> Nested Loop Join (inner) - ................................................-> Filter - ....................................................-> Table "T1" as "A T1" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T1_ID" Unique Scan - ................................................-> Filter - ....................................................-> Table "T7" as "A T7" Access By ID - ........................................................-> Bitmap - ............................................................-> Index "PK_T7_ID" Unique Scan - ............................-> Filter - ................................-> Table "T3" as "A T3" Access By ID - ....................................-> Bitmap - ........................................-> Index "PK_T3_ID" Unique Scan - """ - - act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.expected_stdout = 'Completed.' act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From d79e2dda74600b8e9409a68564cd37d99e7919b0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 18 Nov 2024 10:00:32 +0300 Subject: [PATCH 0261/1064] Added/Updated tests\bugs\gh_8310_test.py: Currently the ticket is incompletely checked - SEE NOTES. Checked on 6.0.0.532; 5.0.2.1567. --- tests/bugs/gh_8310_test.py | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/bugs/gh_8310_test.py diff --git a/tests/bugs/gh_8310_test.py b/tests/bugs/gh_8310_test.py new file mode 100644 index 00000000..89a082e1 --- /dev/null +++ b/tests/bugs/gh_8310_test.py @@ -0,0 +1,65 @@ +#coding:utf-8 + +""" +ID: issue-8310 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8310 +TITLE: Collect network statistics and make it available for the user applications +DESCRIPTION: +NOTES: + [18.11.2024] pzotov + ::: NB ::: Currently the ticket is incompletely checked. + Test verifies only ability to obtain in ISQL wire counters and statistics as described in the doc. + More complex test(s) will be implemented after firevird-driver become to recognize appropriate API changes. + + Checked on 6.0.0.532; 5.0.2.1567. +""" +import os +import pytest +from firebird.qa import * + +db = db_factory() + +test_sql = f""" + set bail on; + set list on; + set wire; + out {os.devnull}; + select count(*) from rdb$fields; + show wire_stat; + out; +""" + +act = isql_act('db', test_sql, substitutions=[ ('\\d+', ''), ('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action): + + act.expected_stdout = """ + Wire logical statistics: + send packets = 6 + recv packets = 5 + send bytes = 184 + recv bytes = 224 + Wire physical statistics: + send packets = 3 + recv packets = 2 + send bytes = 184 + recv bytes = 224 + roundtrips = 2 + + Wire logical statistics: + send packets = 18 + recv packets = 15 + send bytes = 1480 + recv bytes = 944 + Wire physical statistics: + send packets = 15 + recv packets = 11 + send bytes = 1480 + recv bytes = 944 + roundtrips = 11 + """ + act.execute(combine_output = True) + + assert act.clean_stdout == act.clean_expected_stdout + From 6448e5e1062a44a265ff85eb2c1fec01211794c6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 18 Nov 2024 10:02:25 +0300 Subject: [PATCH 0262/1064] Added/Updated tests\bugs\gh_8310_test.py: minor change: fixed typo. --- tests/bugs/gh_8310_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8310_test.py b/tests/bugs/gh_8310_test.py index 89a082e1..f67093e1 100644 --- a/tests/bugs/gh_8310_test.py +++ b/tests/bugs/gh_8310_test.py @@ -9,7 +9,7 @@ [18.11.2024] pzotov ::: NB ::: Currently the ticket is incompletely checked. Test verifies only ability to obtain in ISQL wire counters and statistics as described in the doc. - More complex test(s) will be implemented after firevird-driver become to recognize appropriate API changes. + More complex test(s) will be implemented after firebird-driver become to recognize appropriate API changes. Checked on 6.0.0.532; 5.0.2.1567. """ From 50b088f0f648c20909d62d89e8f63576cb5d682b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 18 Nov 2024 13:13:17 +0300 Subject: [PATCH 0263/1064] Added/Updated tests\functional\tabloid\test_35f56933.py: Checked on 6.0.0.532 --- tests/functional/tabloid/test_35f56933.py | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/functional/tabloid/test_35f56933.py diff --git a/tests/functional/tabloid/test_35f56933.py b/tests/functional/tabloid/test_35f56933.py new file mode 100644 index 00000000..9239c3d3 --- /dev/null +++ b/tests/functional/tabloid/test_35f56933.py @@ -0,0 +1,68 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://github.com/FirebirdSQL/firebird/commit/35f56933306d9d486a5c66da8f85b4be214860d9 +TITLE: Fixed cardinality mistake for invariant booleans +DESCRIPTION: +NOTES: + [18.11.2024] pzotov + 1. No ticket has been created for this test. + 2. Currently one may see cardinality to nodes of explained plan only in the output of rdb$sql.explain() + 3. Before fix, last two nodes of query like 'select ... from where 1=1' had different values + of cardinality. If cardinality for last node was is then for node it was wrongly evaluated + as power(C,2). After fix these two values must be the same. + + Thanks to dimitr for the explaiantion on implementing the test. + + Confirmed problem on 6.0.0.520. + Checked on 6.0.0.532 -- all fine. +""" + +import pytest +from firebird.qa import * + +test_sql = f""" + set list on; + recreate sequence g; + recreate table test(id int primary key); + insert into test select gen_id(g,1) from rdb$types,rdb$types rows 1000; + commit; + select + t.access_path + ,iif( count(distinct t.cardinality)over() = 1 + ,'EXPECTED: THE SAME.' + ,'UNEXPECTED: min = ' || min(t.cardinality)over() || ', max=' || max(t.cardinality)over() + ) as cardinality_values + from ( + select + p.plan_line + ,p.record_source_id + ,p.parent_record_source_id + ,p.level + ,p.cardinality + ,cast(p.access_path as varchar(30)) as access_path + ,max(p.plan_line)over() - p.plan_line as mx + from rdb$sql.explain('select count(*) from test where 1=1') as p + ) t + where t.mx in (0,1) + ; +""" + +db = db_factory() +act = isql_act('db', test_sql, substitutions=[('[ \t]+', ' ')]) + + +@pytest.mark.version('>=6') +def test_1(act: Action): + + act.expected_stdout = """ + ACCESS_PATH -> Filter (preliminary) + CARDINALITY_VALUES EXPECTED: THE SAME. + + ACCESS_PATH -> Table "TEST" Full Scan + CARDINALITY_VALUES EXPECTED: THE SAME. + """ + act.execute(combine_output = True) + + assert act.clean_stdout == act.clean_expected_stdout From c0e48cc49873ed3d2c8b1b2847a3f4ddabd14869 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 18 Nov 2024 16:42:40 +0300 Subject: [PATCH 0264/1064] Added/Updated tests\bugs\gh_8113_test.py: Checked on 6.0.0.532 --- tests/bugs/gh_8113_test.py | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/bugs/gh_8113_test.py diff --git a/tests/bugs/gh_8113_test.py b/tests/bugs/gh_8113_test.py new file mode 100644 index 00000000..1bc71717 --- /dev/null +++ b/tests/bugs/gh_8113_test.py @@ -0,0 +1,71 @@ +#coding:utf-8 + +""" +ID: issue-8113 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8113 +TITLE: UNION ALL optimization with constant false condition +DESCRIPTION: + Test uses script based on example from ticket. + Number of UNIONed parts is defined via UNION_MEMBERS_CNT variable. + We compare number of natural reads with threshold = 1 (see MAX_ALLOWED_NAT_READS). +NOTES: + [18.11.2024] pzotov + Confirmed excessive reads on 6.0.0.520. + Checked on 6.0.0.532 -- all OK. +""" + +import pytest +from firebird.qa import * + +######################### +MAX_ALLOWED_NAT_READS = 1 +UNION_MEMBERS_CNT = 254 +######################### + +view_ddl = f'recreate view v_test as ' + '\nunion all '.join( [f'select {i} as x from test' for i in range(UNION_MEMBERS_CNT)] ) + '\n;' +init_sql = f""" + recreate table test(id int); + insert into test(id) values(0); + commit; + {view_ddl} +""" + +db = db_factory(init = init_sql) + +act = python_act('db') + +#----------------------------------------------------------- + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + msg_prefix = 'Number of natural reads:' + expected_txt = 'EXPECTED' + nat_reads = {} + with act.db.connect() as con: + cur = con.cursor() + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = upper('test')") + src_relation_id = cur.fetchone()[0] + nat_reads[src_relation_id] = 0 + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + nat_reads[src_relation_id] = -x_table.sequential + + cur.execute(f"select /* trace_tag */ x from v_test where x = {UNION_MEMBERS_CNT-1}") + data = cur.fetchall() + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + nat_reads[src_relation_id] += x_table.sequential + + if nat_reads[src_relation_id] <= MAX_ALLOWED_NAT_READS: + print(f'{msg_prefix} {expected_txt}') + else: + print(f'{msg_prefix} UNEXPECTED: {nat_reads[src_relation_id]} - greater than threshold = {MAX_ALLOWED_NAT_READS}.') + + act.expected_stdout = f""" + {msg_prefix} {expected_txt} + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 943525b4a7305b472ca73e2d92514fa271e493cc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 18 Nov 2024 17:01:33 +0300 Subject: [PATCH 0265/1064] Added/Updated tests\bugs\gh_7853_test.py: Remove upper bound for version after this feature was front-ported to 6.x in commit 0d72b8097c292dabb5c9a257a157f20d9362ab26 (16.11.23). --- tests/bugs/gh_7853_test.py | 46 +++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/tests/bugs/gh_7853_test.py b/tests/bugs/gh_7853_test.py index 7def6d93..a2d62b25 100644 --- a/tests/bugs/gh_7853_test.py +++ b/tests/bugs/gh_7853_test.py @@ -2,7 +2,7 @@ """ ID: issue-7853 -ISSUE: 7853 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/7853 TITLE: Do not consider non-deterministic expressions as invariants in pre-filters DESCRIPTION: Change in FB 5.x was pushed 14.12.2023 20:06: @@ -29,6 +29,10 @@ Checked on 5.0.0.1304 ::: NB ::: Build 6.0.0.180 - FAILS because this PR still not pushed in master branch. Waiting for commit. + + [18.11.2024] pzotov + Remove upper bound for version after this feature was front-ported to 6.x in commit 0d72b8097c292dabb5c9a257a157f20d9362ab26 (16.11.23). + Checked on 6.0.0.532. """ import pytest @@ -63,40 +67,40 @@ expected_stdout = """ Select Expression - ####-> Aggregate - ########-> Filter - ############-> Table "TMAIN" as "M0" Full Scan + ....-> Aggregate + ........-> Filter + ............-> Table "TMAIN" as "M0" Full Scan Select Expression - ####-> Aggregate - ########-> Filter - ############-> Table "TMAIN" as "M1" Full Scan + ....-> Aggregate + ........-> Filter + ............-> Table "TMAIN" as "M1" Full Scan Select Expression - ####-> Aggregate - ########-> Filter - ############-> Table "TMAIN" as "M2" Full Scan + ....-> Aggregate + ........-> Filter + ............-> Table "TMAIN" as "M2" Full Scan Select Expression - ####-> Aggregate - ########-> Filter - ############-> Table "TMAIN" as "M3" Full Scan + ....-> Aggregate + ........-> Filter + ............-> Table "TMAIN" as "M3" Full Scan Sub-query (invariant) - ####-> Singularity Check - ########-> Aggregate - ############-> Table "TDETL" as "D" Full Scan + ....-> Singularity Check + ........-> Aggregate + ............-> Table "TDETL" as "D" Full Scan Select Expression - ####-> Aggregate - ########-> Filter - ############-> Table "TMAIN" as "M4" Full Scan + ....-> Aggregate + ........-> Filter + ............-> Table "TMAIN" as "M4" Full Scan """ #--------------------------------------------------------- -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped #--------------------------------------------------------- -@pytest.mark.version('>=5.0,<6') +@pytest.mark.version('>=5.0') def test_1(act: Action, capsys): with act.db.connect() as con: cur = con.cursor() From cf374b406a79804906a34fc8a76fa709e1609d8a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 19 Nov 2024 10:13:30 +0300 Subject: [PATCH 0266/1064] Added/Updated tests\bugs\core_5381_test.py: Added max allowed time for prepare duration and appropriate check (suggested by dimitr). --- tests/bugs/core_5381_test.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_5381_test.py b/tests/bugs/core_5381_test.py index 8048d7f4..ccc31232 100644 --- a/tests/bugs/core_5381_test.py +++ b/tests/bugs/core_5381_test.py @@ -11,21 +11,29 @@ FBTEST: bugs.core_5381 NOTES: [17.11.2024] pzotov - Re-implemented. No sense to check execution time or execution plan. We have to ensure only ability of engine to complete prerape_statement. + [19.11.2024] pzotov + Added max allowed time for prepare duration and appropriate check (suggested by dimitr). + Confirmed bug on 3.0.1.32609 (27-sep-2016), got in trace: 2024-11-08T00:42:49.8710 ERROR AT JStatement::prepare 335544382 : request size limit exceeded Checked on 3.0.13.33794, 4.0.6.3168, 5.0.2.1553, 6.0.0.520 """ +import datetime as py_dt +from datetime import timedelta import pytest from firebird.qa import * from firebird.driver import DatabaseError +################### +MAX_PREPARE_TIME_MS=1000 +################### + init_sql = """ recreate view test_view as select 1 x from rdb$database; recreate view inner_view as select 1 x from rdb$database; @@ -120,12 +128,15 @@ def test_1(act: Action, capsys): where a.id = 1 ; """ - + td = 86400000 with act.db.connect() as con: cur = con.cursor() ps = None try: + t1=py_dt.datetime.now() ps = cur.prepare(test_sql) + t2=py_dt.datetime.now() + td = int((t2-t1).total_seconds() * 1000) # milliseconds print('Completed.') except DatabaseError as e: print(e.__str__()) @@ -135,6 +146,7 @@ def test_1(act: Action, capsys): ps.free() act.expected_stdout = 'Completed.' - act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout + assert td < MAX_PREPARE_TIME_MS, f'Prepare time: {td} ms - greater than max allowed {MAX_PREPARE_TIME_MS} ms.' + From 890ebd92017a0a13b93062f2d3e38745454a09e3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 20 Nov 2024 20:14:16 +0300 Subject: [PATCH 0267/1064] Added/Updated tests\functional\transactions\test_read_consist_sttm_restart_on_merge_01.py: added 'ROWS nn' after 'ORDER BY ...' clause, otherwise engine can choose 'PLAN SORT' which leads to materialization of cursor resultset and, in turn, to increased statement restart count. See notes. --- .../test_read_consist_sttm_restart_on_merge_01.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py index 9f021352..d3b5281e 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_merge_01.py @@ -142,6 +142,16 @@ [25.11.2023] pzotov Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). Merge expression defined in 'SQL_TO_BE_RESTARTED' must NOT end with semicolon! + + [20.11.2024] pzotov + ::: ACHTUNG ::: ENGINE MUST NOT USE 'PLAN SORT' IN THE QUERY WHICH HAS TO BE RESTARTED IN THIS TEST! + Number of statement restarts CAN BE GREATER than expected! This occurs if a table (which is handled) has no appropriate index or if optimizer decides to use + external sort (e.g. 'PLAN SORT') instead of index navigation. This affects only FB 6.x and can be seen on snapshots since 14.11.2024, see: + https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81 ("Cost-based decision between ORDER and SORT plans (#8316)"). + This result was explained by Vlad (letter 19.11.2024 09:59): external sort forces engine to materialize cursor resultset. In such state, in turn, cursor can not + see records which not fall to this cursor expression or did not exist when cursor started its job. + Because of that, SQL_TO_BE_RESTARTED expression was changed: 'ROWS 10' was added after 'ORDER BY' clause to make optimizer choose 'PLAN ORDER' every time. + Perhaps, this change is temporary solution. """ import subprocess @@ -226,7 +236,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: SQL_TO_BE_RESTARTED = f""" merge /* {SQL_TAG_THAT_WE_WAITING_FOR} */ into {target_obj} t - using (select * from {target_obj} order by id) s on s.id=t.id + using (select * from {target_obj} order by id ROWS 10) s on s.id=t.id when matched then update set t.id = -t.id, t.x = -s.x when not matched then From 4337828fb5311ccbc12fcfc2a8cec45843961d03 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 20 Nov 2024 20:14:32 +0300 Subject: [PATCH 0268/1064] Added/Updated tests\functional\transactions\test_read_consist_statement_delete_undone_02.py: added 'ROWS nn' after 'ORDER BY ...' clause, otherwise engine can choose 'PLAN SORT' which leads to materialization of cursor resultset and, in turn, to increased statement restart count. See notes. --- .../test_read_consist_statement_delete_undone_02.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py b/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py index 75dc97ce..97e7028e 100644 --- a/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py +++ b/tests/functional/transactions/test_read_consist_statement_delete_undone_02.py @@ -126,6 +126,16 @@ NB! Worker transaction must running in WAIT mode - in contrary to Tx that we start in our monitoring loop. Checked on WI-T6.0.0.48, WI-T5.0.0.1211, WI-V4.0.4.2988. + + [20.11.2024] pzotov + ::: ACHTUNG ::: ENGINE MUST NOT USE 'PLAN SORT' IN THE QUERY WHICH HAS TO BE RESTARTED IN THIS TEST! + Number of statement restarts CAN BE GREATER than expected! This occurs if a table (which is handled) has no appropriate index or if optimizer decides to use + external sort (e.g. 'PLAN SORT') instead of index navigation. This affects only FB 6.x and can be seen on snapshots since 14.11.2024, see: + https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81 ("Cost-based decision between ORDER and SORT plans (#8316)"). + This result was explained by Vlad (letter 19.11.2024 09:59): external sort forces engine to materialize cursor resultset. In such state, in turn, cursor can not + see records which not fall to this cursor expression or did not exist when cursor started its job. + Because of that, SQL_TO_BE_RESTARTED expression was changed: 'ROWS 10' was added after 'ORDER BY' clause to make optimizer choose 'PLAN ORDER' every time. + Perhaps, this change is temporary solution. """ import subprocess @@ -211,7 +221,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: for checked_mode in('table', 'view'): target_obj = 'test' if checked_mode == 'table' else 'v_test' - SQL_TO_BE_RESTARTED = f'delete /* {SQL_TAG_THAT_WE_WAITING_FOR} */ from {target_obj} where x not in (select x from {target_obj} where id >= 4) order by id desc' + SQL_TO_BE_RESTARTED = f'delete /* {SQL_TAG_THAT_WE_WAITING_FOR} */ from {target_obj} where x not in (select x from {target_obj} where id >= 4) order by id desc ROWS 10' # add rows with ID = 1,2,3,4,5: sql_addi=''' From 9435ab18f442ef67d10bc175e854660b096ac08f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 20 Nov 2024 20:14:46 +0300 Subject: [PATCH 0269/1064] Added/Updated tests\functional\transactions\test_read_consist_sttm_restart_on_update_03.py: added 'ROWS nn' after 'ORDER BY ...' clause, otherwise engine can choose 'PLAN SORT' which leads to materialization of cursor resultset and, in turn, to increased statement restart count. See notes. --- ..._read_consist_sttm_restart_on_update_03.py | 107 ++++++++++-------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py index 418877a0..41deef2b 100644 --- a/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py +++ b/tests/functional/transactions/test_read_consist_sttm_restart_on_update_03.py @@ -151,8 +151,19 @@ NB! Worker transaction must running in WAIT mode - in contrary to Tx that we start in our monitoring loop. Checked on WI-T6.0.0.48, WI-T5.0.0.1211, WI-V4.0.4.2988. + + [20.11.2024] pzotov + ::: ACHTUNG ::: ENGINE MUST NOT USE 'PLAN SORT' IN THE QUERY WHICH HAS TO BE RESTARTED IN THIS TEST! + Number of statement restarts CAN BE GREATER than expected! This occurs if a table (which is handled) has no appropriate index or if optimizer decides to use + external sort (e.g. 'PLAN SORT') instead of index navigation. This affects only FB 6.x and can be seen on snapshots since 14.11.2024, see: + https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81 ("Cost-based decision between ORDER and SORT plans (#8316)"). + This result was explained by Vlad (letter 19.11.2024 09:59): external sort forces engine to materialize cursor resultset. In such state, in turn, cursor can not + see records which not fall to this cursor expression or did not exist when cursor started its job. + Because of that, SQL_TO_BE_RESTARTED expression was changed: 'ROWS 10' was added after 'ORDER BY' clause to make optimizer choose 'PLAN ORDER' every time. + Perhaps, this change is temporary solution. """ +import inspect import subprocess import re from pathlib import Path @@ -187,11 +198,18 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec t1=py_dt.datetime.now() required_concurrent_found = None concurrent_tx_pattern = re.compile('concurrent transaction number is \\d+', re.IGNORECASE) + + iter = 0 while True: concurrent_tx_number = None concurrent_runsql = '' tx_monitoring.begin() try: + sql_tag_wait_for_lock_record = f'/* {inspect.stack()[0][3]}(), iter: {iter} */' + sql_words = sql_to_lock_record.split() + sql_words.insert(1, sql_tag_wait_for_lock_record) + sql_to_lock_record = ' '.join(sql_words) + iter += 1 cur_monitoring.execute(sql_to_lock_record) except DatabaseError as exc: # Failed: SQL execution failed with: deadlock @@ -206,7 +224,6 @@ def wait_for_record_become_locked(tx_monitoring, cur_monitoring, sql_to_lock_rec if SQL_TAG_THAT_WE_WAITING_FOR in concurrent_runsql: required_concurrent_found = 1 - # pytest.fail(f"Can not upd, concurrent TX = {concurrent_tx_number}, sql: {concurrent_runsql}") finally: tx_monitoring.rollback() @@ -233,7 +250,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: for checked_mode in('table', 'view'): target_obj = 'test' if checked_mode == 'table' else 'v_test' - SQL_TO_BE_RESTARTED = f"update /* {SQL_TAG_THAT_WE_WAITING_FOR} */ {target_obj} set id = -id order by id" + SQL_TO_BE_RESTARTED = f"update /* {SQL_TAG_THAT_WE_WAITING_FOR} */ {target_obj} set id = -id order by id ROWS 10" # add rows with ID = 1, 2: sql_addi = f''' @@ -277,7 +294,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: ### L O C K E R - 1 ### ######################### - con_lock_1.execute_immediate( f'update {target_obj} set id=id where id = 2' ) + con_lock_1.execute_immediate( f'update /* LOCKER-1 */ {target_obj} set id=id where id = 2' ) worker_sql = f''' set list on; @@ -298,7 +315,7 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: set wng off; set count on; - -- THIS MUST BE LOCKED: + -- WORKER. THIS MUST BE LOCKED NOW BY LOCKER_i: {SQL_TO_BE_RESTARTED}; -- check results: @@ -340,11 +357,11 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: ######################### ### L O C K E R - 2 ### ######################### - con_lock_2.execute_immediate( f'insert into {target_obj}(id) values(110)' ) - con_lock_2.execute_immediate( f'insert into {target_obj}(id) values(-11)' ) + con_lock_2.execute_immediate( f'insert /* LOCKER-2 */ into {target_obj}(id) values(110)' ) + con_lock_2.execute_immediate( f'insert /* LOCKER-2 */ into {target_obj}(id) values(-11)' ) con_lock_2.commit() - con_lock_2.execute_immediate( f'update {target_obj} set id=id where id = 110' ) - con_lock_2.execute_immediate( f'update {target_obj} set id=id where id = -11' ) + con_lock_2.execute_immediate( f'update /* LOCKER-2 */ {target_obj} set id=id where id = 110' ) + con_lock_2.execute_immediate( f'update /* LOCKER-2 */ {target_obj} set id=id where id = -11' ) ######################### ### L O C K E R - 1 ### @@ -356,11 +373,11 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: wait_for_record_become_locked(tx_monitoring, cur_monitoring, f'update {target_obj} set id=id where id=2', SQL_TAG_THAT_WE_WAITING_FOR) # If we come here then it means that record with ID = 2 for sure is locked by WORKER. - con_lock_1.execute_immediate( f'insert into {target_obj}(id) values(120)' ) - con_lock_1.execute_immediate( f'insert into {target_obj}(id) values(-12)' ) + con_lock_1.execute_immediate( f'insert /* LOCKER-1 */ into {target_obj}(id) values(120)' ) + con_lock_1.execute_immediate( f'insert /* LOCKER-1 */ into {target_obj}(id) values(-12)' ) con_lock_1.commit() - con_lock_1.execute_immediate( f'update {target_obj} set id=id where id = 120' ) - con_lock_1.execute_immediate( f'update {target_obj} set id=id where id = -12' ) + con_lock_1.execute_immediate( f'update /* LOCKER-1 */ {target_obj} set id=id where id = 120' ) + con_lock_1.execute_immediate( f'update /* LOCKER-1 */ {target_obj} set id=id where id = -12' ) ######################### @@ -374,11 +391,11 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: # If we come here then it means that TWO records with ID = -11 and 110 for sure are locked by WORKER. - con_lock_2.execute_immediate( f'insert into {target_obj}(id) values(130)' ) - con_lock_2.execute_immediate( f'insert into {target_obj}(id) values(-13)' ) + con_lock_2.execute_immediate( f'insert into /* LOCKER-2 */ {target_obj}(id) values(130)' ) + con_lock_2.execute_immediate( f'insert into /* LOCKER-2 */ {target_obj}(id) values(-13)' ) con_lock_2.commit() - con_lock_2.execute_immediate( f'update {target_obj} set id=id where id = 130' ) - con_lock_2.execute_immediate( f'update {target_obj} set id=id where id = -13' ) + con_lock_2.execute_immediate( f'update /* LOCKER-2 */ {target_obj} set id=id where id = 130' ) + con_lock_2.execute_immediate( f'update /* LOCKER-2 */ {target_obj} set id=id where id = -13' ) ######################### ### L O C K E R - 1 ### @@ -391,11 +408,11 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: # If we come here then it means that TWO records with ID = -12 and 120 for sure are locked by WORKER. - con_lock_1.execute_immediate( f'insert into {target_obj}(id) values(140)' ) - con_lock_1.execute_immediate( f'insert into {target_obj}(id) values(-14)' ) + con_lock_1.execute_immediate( f'insert /* LOCKER-1 */ into {target_obj}(id) values(140)' ) + con_lock_1.execute_immediate( f'insert /* LOCKER-1 */ into {target_obj}(id) values(-14)' ) con_lock_1.commit() - con_lock_1.execute_immediate( f'update {target_obj} set id=id where id = 140' ) - con_lock_1.execute_immediate( f'update {target_obj} set id=id where id = -14' ) + con_lock_1.execute_immediate( f'update /* LOCKER-1 */ {target_obj} set id=id where id = 140' ) + con_lock_1.execute_immediate( f'update /* LOCKER-1 */ {target_obj} set id=id where id = -14' ) ######################### ### L O C K E R - 2 ### @@ -429,32 +446,32 @@ def test_1(act: Action, fn_worker_sql: Path, fn_worker_log: Path, fn_worker_err: expected_stdout_worker = f""" checked_mode: {checked_mode}, STDLOG: Records affected: 10 - checked_mode: {checked_mode}, STDLOG: ID - checked_mode: {checked_mode}, STDLOG: ======= - checked_mode: {checked_mode}, STDLOG: -140 - checked_mode: {checked_mode}, STDLOG: -130 - checked_mode: {checked_mode}, STDLOG: -120 - checked_mode: {checked_mode}, STDLOG: -110 - checked_mode: {checked_mode}, STDLOG: -2 - checked_mode: {checked_mode}, STDLOG: -1 - checked_mode: {checked_mode}, STDLOG: 11 - checked_mode: {checked_mode}, STDLOG: 12 - checked_mode: {checked_mode}, STDLOG: 13 - checked_mode: {checked_mode}, STDLOG: 14 + checked_mode: {checked_mode}, STDLOG: ID + checked_mode: {checked_mode}, STDLOG: + checked_mode: {checked_mode}, STDLOG: -140 + checked_mode: {checked_mode}, STDLOG: -130 + checked_mode: {checked_mode}, STDLOG: -120 + checked_mode: {checked_mode}, STDLOG: -110 + checked_mode: {checked_mode}, STDLOG: -2 + checked_mode: {checked_mode}, STDLOG: -1 + checked_mode: {checked_mode}, STDLOG: 11 + checked_mode: {checked_mode}, STDLOG: 12 + checked_mode: {checked_mode}, STDLOG: 13 + checked_mode: {checked_mode}, STDLOG: 14 checked_mode: {checked_mode}, STDLOG: Records affected: 10 - checked_mode: {checked_mode}, STDLOG: OLD_ID OP SNAP_NO_RANK - checked_mode: {checked_mode}, STDLOG: ======= ====== ===================== - checked_mode: {checked_mode}, STDLOG: 1 UPD 1 - checked_mode: {checked_mode}, STDLOG: -14 UPD 2 - checked_mode: {checked_mode}, STDLOG: -13 UPD 2 - checked_mode: {checked_mode}, STDLOG: -12 UPD 2 - checked_mode: {checked_mode}, STDLOG: -11 UPD 2 - checked_mode: {checked_mode}, STDLOG: 1 UPD 2 - checked_mode: {checked_mode}, STDLOG: 2 UPD 2 - checked_mode: {checked_mode}, STDLOG: 110 UPD 2 - checked_mode: {checked_mode}, STDLOG: 120 UPD 2 - checked_mode: {checked_mode}, STDLOG: 130 UPD 2 - checked_mode: {checked_mode}, STDLOG: 140 UPD 2 + checked_mode: {checked_mode}, STDLOG: OLD_ID OP SNAP_NO_RANK + checked_mode: {checked_mode}, STDLOG: + checked_mode: {checked_mode}, STDLOG: 1 UPD 1 + checked_mode: {checked_mode}, STDLOG: -14 UPD 2 + checked_mode: {checked_mode}, STDLOG: -13 UPD 2 + checked_mode: {checked_mode}, STDLOG: -12 UPD 2 + checked_mode: {checked_mode}, STDLOG: -11 UPD 2 + checked_mode: {checked_mode}, STDLOG: 1 UPD 2 + checked_mode: {checked_mode}, STDLOG: 2 UPD 2 + checked_mode: {checked_mode}, STDLOG: 110 UPD 2 + checked_mode: {checked_mode}, STDLOG: 120 UPD 2 + checked_mode: {checked_mode}, STDLOG: 130 UPD 2 + checked_mode: {checked_mode}, STDLOG: 140 UPD 2 checked_mode: {checked_mode}, STDLOG: Records affected: 11 """ From 3225efe19224a089041a56ae670e9bed4381f221 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 21 Nov 2024 07:57:46 +0300 Subject: [PATCH 0270/1064] Added/Updated tests\functional\basic\isql\test_00.py: adjust output: added lines related to wire stat --- tests/functional/basic/isql/test_00.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/basic/isql/test_00.py b/tests/functional/basic/isql/test_00.py index 2b29d7a0..ae5c047c 100644 --- a/tests/functional/basic/isql/test_00.py +++ b/tests/functional/basic/isql/test_00.py @@ -77,7 +77,7 @@ SHOW [] -- display system information = CHECK, COLLATION, DATABASE, DOMAIN, EXCEPTION, FILTER, FUNCTION, GENERATOR, GRANT, INDEX, PACKAGE, PROCEDURE, ROLE, SQL DIALECT, - SYSTEM, TABLE, TRIGGER, VERSION, USERS, VIEW + SYSTEM, TABLE, TRIGGER, VERSION, USERS, VIEW, WIRE_STATISTICS EXIT -- exit and commit changes QUIT -- exit and roll back changes All commands may be abbreviated to letters in CAPitals @@ -103,6 +103,7 @@ SET TIME -- toggle display of timestamp with DATE values SET TERM -- change statement terminator string SET WIDTH [] -- set/unset print width to for column + SET WIRE_stats -- toggle display of wire (network) statistics All commands may be abbreviated to letters in CAPitals """ From 1f1eb1725da12927d7b9228fc4697f5bb8194755 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 26 Nov 2024 16:15:53 +0300 Subject: [PATCH 0271/1064] Updated tests\bugs\gh_0310_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_0310_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_0310_test.py b/tests/bugs/gh_0310_test.py index 08f3fffb..69a041d4 100644 --- a/tests/bugs/gh_0310_test.py +++ b/tests/bugs/gh_0310_test.py @@ -1613,6 +1613,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME BLOB RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME BLOBID + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME BLOB_APPEND RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME BLOCK @@ -2407,6 +2409,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME TARGET RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME TEMP + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME TEMPORARY RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME THEN @@ -2526,7 +2530,7 @@ RDB$KEYWORD_NAME ZONE RDB$KEYWORD_RESERVED - Records affected: 503 + Records affected: 505 """ @pytest.mark.disabled_in_forks From 06f4702b7016cc1c8fd706c1359594dab5c9266e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 26 Nov 2024 16:23:17 +0300 Subject: [PATCH 0272/1064] Added/Updated tests\bugs\gh_0310_test.py: added forgotten corrections for expected output in FB 5.x --- tests/bugs/gh_0310_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_0310_test.py b/tests/bugs/gh_0310_test.py index 69a041d4..c039099b 100644 --- a/tests/bugs/gh_0310_test.py +++ b/tests/bugs/gh_0310_test.py @@ -164,6 +164,9 @@ RDB$KEYWORD_NAME BLOB RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME BLOBID + RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME BLOB_APPEND RDB$KEYWORD_RESERVED @@ -1337,6 +1340,9 @@ RDB$KEYWORD_NAME TARGET RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME TEMP + RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME TEMPORARY RDB$KEYWORD_RESERVED @@ -1515,7 +1521,7 @@ RDB$KEYWORD_RESERVED - Records affected: 496 + Records affected: 498 """ expected_stdout_6 = """ From de2237e06e25ad6606c6b74310f1912ea6c55c46 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 28 Nov 2024 13:34:30 +0300 Subject: [PATCH 0273/1064] Added/Updated tests\bugs\gh_8323_test.py: see notes. --- tests/bugs/gh_8323_test.py | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/bugs/gh_8323_test.py diff --git a/tests/bugs/gh_8323_test.py b/tests/bugs/gh_8323_test.py new file mode 100644 index 00000000..22713c54 --- /dev/null +++ b/tests/bugs/gh_8323_test.py @@ -0,0 +1,49 @@ +#coding:utf-8 + +""" +ID: issue-8323 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8323 +TITLE: Add AUTO RELEASE TEMP BLOBID transaction option +NOTES: + [28.11.2024] pzotov + 1. Test verifies only syntax extension of SET TRANSACTION, i.e. ability to use 'AUTO RELEASE TEMP BLOBID' clause. + Handling with temporary BLOBID can not be tested in ISQL and will be checked when firebird-driver will support this. + 2. Presense of mon$transactions.mon$auto_release_temp_blobid column not checked: FB 5.x currently missed it. + + Discussed with Vlad, letters 28.11.2024. + + Checked on 6.0.0.535, 5.0.2.1569 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail on; + set list on; + set blob all; + recreate table test(b blob); + commit; + + -- makes the transaction release a temporary ID of a user BLOB just after its materialization + set transaction AUTO RELEASE TEMP BLOBID; + + insert into test values('qwerty') returning b as blob_column_id; + -- TEMPORARY (?) DISABLED: FB 5.X HAS NO SUCH FIELD: + -- select mon$auto_release_temp_blobid from mon$transactions where mon$transaction_id = current_transaction; + commit; +""" + +act = isql_act('db', test_script, substitutions = [('BLOB_COLUMN_ID .*', '')]) + +expected_stdout = """ + qwerty +""" + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3ea708d07662c05b44a5308cf18d4d01724a1411 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 29 Nov 2024 12:29:31 +0300 Subject: [PATCH 0274/1064] Added/Updated tests\bugs\core_0214_test.py: fully re-implemented. See notes. --- tests/bugs/core_0214_test.py | 436 +++++++++++++++++++++-------------- 1 file changed, 258 insertions(+), 178 deletions(-) diff --git a/tests/bugs/core_0214_test.py b/tests/bugs/core_0214_test.py index 0f7ddf5c..3e0e48d1 100644 --- a/tests/bugs/core_0214_test.py +++ b/tests/bugs/core_0214_test.py @@ -2,195 +2,275 @@ """ ID: issue-542 -ISSUE: 542 -TITLE: Count ( DISTINCT ... ) is too slow +ISSUE: https://github.com/FirebirdSQL/firebird/issues/542 +TITLE: Count (DISTINCT ...) is too slow DESCRIPTION: - This test does following: - 1. Creates several tables with different number of unique values in field ID. - 2. Measures for each table time for two statements: - 2.1. select count(*) from ( select distinct id from ... ) - vs - 2.2. select count(distinct id) from ... - 3. If time for 2.1 exceeds time for 2.2 more than times - output message - about possible regression. After multiple runs it was found that ratio for - 2.1 vs 2.2 is about 1.05 ... 1.10. Constant (threshold) was selected - to be enough for not to be "violated". JIRA: CORE-214 FBTEST: bugs.core_0214 +NOTES: + [29.11.2024] pzotov + 1. Fix was 31-may-2015, https://sourceforge.net/p/firebird/code/61671/ (3.0.0.31846) + Query 'select count(distinct id) from ' (hereafter "q1") elapsed time: + * before fix: ~840 ms + * after fix: ~248 ms + (and this value is close to the time for query 'select count(*) from (select distinct id from ...)', hereafter "q2") + 2. Test was fully re-implemented: we have to measure difference between cpu.user_time values instead of datediff(). + Each query for each datatype is done times, with storing cpu.user_time difference as array element. + Then we evaluate median value for this array and save it for further comparison with . + 3. It was encountered that for several datatypes ratio between CPU time for q1 and q2 remains unusually high: + * for DECFLOAT it can be about 3...4; + * for VARCHAR it depends on the column length and number of bytes in the charset: + ** for single-byte charset (e.g. win1251 etc) ratio is ~2 for field size ~100 and more than 10 for size 1k ... 4k; + ** for mylti-byte (utf8) ratio is 5...7 for field size ~100 and 35...60 for size 1k ...4k (depends on FB version) + For all other datatypes ratio is about 0.9 ... 1.2. + Time ratio for LIST(distinct ...) was also measured. Results are the same as for COUNT. + Test is considered as passed if ratios for all datatypes are less than . + 4. Because of necessity to measure ratio for datatypes that absent in FB 3.x, it was decided to increase min_version to 4.0 + (plus, there won't be any niticeable changes in FB 3.x code). + 5. A new ticket has been created to describe problem with DECFLOAT and VARCHAR datatypes: + https://github.com/FirebirdSQL/firebird/issues/8330 + (it contains two excel files with comparison for misc datatypes and different declared length of varchar column). + Test for these datatypes will be added after fix of this ticked. + + Checked on Windiws (SS/CS): 6.0.0.535; 5.0.2.1569; 4.0.6.3169. """ - +import psutil +import time import pytest from firebird.qa import * -db = db_factory() - -MAX_DIFF = 3.0 - -test_script = f""" - recreate table test1e1(id int); -- 10^1 distinct values - recreate table test1e2(id int); -- 10^2 distinct values - recreate table test1e3(id int); -- 10^3 distinct values - recreate table test1e4(id int); -- 10^4 distinct values - recreate table test1e5(id int); -- 10^5 distinct values - commit; - - create or alter view v_fill as - with recursive - r as(select 0 i from rdb$database union all select r.i+1 from r where r.i<9) - select r4.i * 10000 + r3.i * 1000 + r2.i * 100 + r1.i * 10 + r0.i as id - from r r4, r r3, r r2, r r1, r r0; - commit; - - insert into test1e1 select mod(id, 10) from v_fill; - insert into test1e2 select mod(id, 100) from v_fill; - insert into test1e3 select mod(id, 1000) from v_fill; - insert into test1e4 select mod(id, 10000) from v_fill; - insert into test1e5 select mod(id, 100000) from v_fill; +#-------------------------------------------------------------------- +def median(lst): + n = len(lst) + s = sorted(lst) + return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None +#-------------------------------------------------------------------- + +########################### +### S E T T I N G S ### +########################### +N_MEASURES = 11 +PAGE_SIZE = 8192 +N_ROWS_CNT= 100000 +MAX_RATIO = 2.0 + +#---------------------------------------------------- +# NOT yet used. See #8330: +TXT_WIDTH_SINGLE_BYTE_ENCODING = int(PAGE_SIZE/2 + 1) +TXT_WIDTH_MULTI_BYTE_ENCODING = int(PAGE_SIZE/2 + 1) +SINGLE_BYTE_TEXT = 'u' * 4097 +MULTI_BYTE_TEXT = 'λ' * 4097 +#---------------------------------------------------- + +init_sql = f""" + set bail on; + recreate table test_one_unique_value( + f_sml smallint -- 0 + ,f_int int -- 1 + ,f_big bigint -- 2 + ,f_i128 int128 -- 3 + ,f_bool boolean -- 4 + ,f_dt date -- 5 + ,f_tm time -- 6 + ,f_ts timestamp -- 7 + ,f_tmtz time with time zone -- 8 + ,f_tstz timestamp with time zone -- 9 + ,f_num numeric(2,2) -- 10 + ,f_dec decimal(2,2) -- 11 + ,f_dbl double precision -- 12 + + -- commented out until #8330 remains unfixed: + --------------------------------------------- + --,f_decf decfloat -- 13 + --,f_txt_1251 varchar({TXT_WIDTH_SINGLE_BYTE_ENCODING}) character set win1251 -- 14 + --,f_txt_utf8 varchar({TXT_WIDTH_MULTI_BYTE_ENCODING}) character set utf8 -- 15 + --------------------------------------------- + ); + + recreate table test_null_in_all_rows( + nul_sml smallint + ,nul_int int + ,nul_big bigint + ,nul_i128 int128 + ,nul_bool boolean + ,nul_dt date + ,nul_tm time + ,nul_ts timestamp + ,nul_tmtz time with time zone + ,nul_tstz timestamp with time zone + ,nul_num numeric(2,2) + ,nul_dec decimal(2,2) + ,nul_dbl double precision + --,nul_decf decfloat + --,nul_txt_1251 varchar({TXT_WIDTH_SINGLE_BYTE_ENCODING}) character set win1251 + --,nul_txt_utf8 varchar({TXT_WIDTH_MULTI_BYTE_ENCODING}) character set utf8 + ); commit; - set list on; - set term ^; - - execute block returns ( - ratio_for_1e1 varchar(150) - ,ratio_for_1e2 varchar(150) - ,ratio_for_1e3 varchar(150) - ,ratio_for_1e4 varchar(150) - ,ratio_for_1e5 varchar(150) - ) - as - -- ############################################ - -- ############ T H R E S H O L D ######## - - -- Before 28.10.2015: 1.85 (changed after letter by dimitr). - -- Probably random disturbance was caused by other (concurrent) processes on test host. - -- Check with new threshold was done on: WI-V2.5.5.26942 (SC) and WI-V3.0.0.32134 (CS/SC/SS). - - declare max_diff_threshold numeric(10,4) = {MAX_DIFF}; - - -- ############################################ - - declare ratio_select_vs_count_1e1 numeric(10,4); - declare ratio_select_vs_count_1e2 numeric(10,4); - declare ratio_select_vs_count_1e3 numeric(10,4); - declare ratio_select_vs_count_1e4 numeric(10,4); - declare ratio_select_vs_count_1e5 numeric(10,4); - declare sel_distinct_1e1_ms int; - declare cnt_distinct_1e1_ms int; - declare sel_distinct_1e2_ms int; - declare cnt_distinct_1e2_ms int; - declare sel_distinct_1e3_ms int; - declare cnt_distinct_1e3_ms int; - declare sel_distinct_1e4_ms int; - declare cnt_distinct_1e4_ms int; - declare sel_distinct_1e5_ms int; - declare cnt_distinct_1e5_ms int; - declare n int; - declare t0 timestamp; + create or alter procedure sp_fill(a_cnt int) returns(id int) as begin - t0='now'; - select count(*) from ( select distinct id from test1e1 ) into n; - sel_distinct_1e1_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - t0='now'; - select count(distinct id) from test1e1 into n; - cnt_distinct_1e1_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - ratio_select_vs_count_1e1 = 1.0000 * sel_distinct_1e1_ms / cnt_distinct_1e1_ms; - - ------------ - - t0='now'; - select count(*) from ( select distinct id from test1e2 ) into n; - sel_distinct_1e2_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - t0='now'; - select count(distinct id) from test1e2 into n; - cnt_distinct_1e2_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - ratio_select_vs_count_1e2 = 1.0000 * sel_distinct_1e2_ms / cnt_distinct_1e2_ms; - - ------------ - - t0='now'; - select count(*) from ( select distinct id from test1e3 ) into n; - sel_distinct_1e3_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - t0='now'; - select count(distinct id) from test1e3 into n; - cnt_distinct_1e3_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - ratio_select_vs_count_1e3 = 1.0000 * sel_distinct_1e3_ms / cnt_distinct_1e3_ms; - - ------------ - - t0='now'; - select count(*) from ( select distinct id from test1e4 ) into n; - sel_distinct_1e4_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - t0='now'; - select count(distinct id) from test1e4 into n; - cnt_distinct_1e4_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - ratio_select_vs_count_1e4 = 1.0000 * sel_distinct_1e4_ms / cnt_distinct_1e4_ms; - - ------------ - - t0='now'; - select count(*) from ( select distinct id from test1e5 ) into n; - sel_distinct_1e5_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - t0='now'; - select count(distinct id) from test1e5 into n; - cnt_distinct_1e5_ms = datediff(millisecond from t0 to cast('now' as timestamp)); - - ratio_select_vs_count_1e5 = 1.0000 * sel_distinct_1e5_ms / cnt_distinct_1e5_ms; - - ------------ - - ratio_for_1e1 = 'Acceptable'; - ratio_for_1e2 = 'Acceptable'; - ratio_for_1e3 = 'Acceptable'; - ratio_for_1e4 = 'Acceptable'; - ratio_for_1e5 = 'Acceptable'; - - if (1=0 or ratio_select_vs_count_1e1 > max_diff_threshold) then - -- Example: RATIO_FOR_1E1 Regression /* perf_issue_tag */: ratio = 3.3695 > 3.0000 - ratio_for_1e1 = 'Regression /* perf_issue_tag */: ratio = '||ratio_select_vs_count_1e1||' > '||max_diff_threshold; - - if (1=0 or ratio_select_vs_count_1e2 > max_diff_threshold) then - ratio_for_1e2 = 'Regression /* perf_issue_tag */: ratio = '||ratio_select_vs_count_1e2||' > '||max_diff_threshold; - - if (1=0 or ratio_select_vs_count_1e3 > max_diff_threshold) then - ratio_for_1e3 = 'Regression /* perf_issue_tag */: ratio = '||ratio_select_vs_count_1e3||' > '||max_diff_threshold; - - if (1=0 or ratio_select_vs_count_1e4 > max_diff_threshold) then - ratio_for_1e4 = 'Regression /* perf_issue_tag */: ratio = '||ratio_select_vs_count_1e4||' > '||max_diff_threshold; - - if (1=0 or ratio_select_vs_count_1e5 > max_diff_threshold) then - ratio_for_1e5 = 'Regression /* perf_issue_tag */: ratio = '||ratio_select_vs_count_1e5||' > '||max_diff_threshold; - - - suspend; - - end - ^ set term ;^ -""" - -act = isql_act('db', test_script,substitutions = [('[ \t]+', ' ')]) + id = 0; + while (id < a_cnt) do + begin + suspend; + id = id + 1; + end + end ^ + set term ;^ + commit; -expected_stdout = f""" - RATIO_FOR_1E1 Acceptable - RATIO_FOR_1E2 Acceptable - RATIO_FOR_1E3 Acceptable - RATIO_FOR_1E4 Acceptable - RATIO_FOR_1E5 Acceptable + insert into test_one_unique_value ( + f_sml -- 0 + ,f_int -- 1 + ,f_big -- 2 + ,f_i128 -- 3 + ,f_bool -- 4 + ,f_dt -- 5 + ,f_tm -- 6 + ,f_ts -- 7 + ,f_tmtz -- 8 + ,f_tstz -- 9 + ,f_num -- 10 + ,f_dec -- 11 + ,f_dbl -- 12 + --,f_decf -- 13 + --,f_txt_1251 -- 14 + --,f_txt_utf8 -- 15 + ) + select + -32768 -- 0 + ,-2147483648 -- 1 + ,-9223372036854775808 -- 2 + ,-170141183460469231731687303715884105728 -- 3 + ,true -- 4 + ,date '19.12.2023' -- 5 + ,time '23:59:59' -- 6 + ,timestamp '19.12.2023 23:59:59' -- 7 + ,time '11:11:11.111 Indian/Cocos' -- 8 + ,timestamp '2018-12-31 12:31:42.543 Pacific/Fiji' -- 9 + ,-327.68 -- 10 + ,-327.68 -- 11 + ,pi() -- 12 + --,exp(1) -- cast(-9.999999999999999999999999999999999E6144 as decfloat(34)) -- 13 + --,lpad('', {TXT_WIDTH_SINGLE_BYTE_ENCODING}, '{SINGLE_BYTE_TEXT}') -- 14 + --,lpad('', {TXT_WIDTH_MULTI_BYTE_ENCODING}, '{MULTI_BYTE_TEXT}') -- 15 + from sp_fill({N_ROWS_CNT}) as p; + + insert into test_null_in_all_rows + select + null -- 0 + ,null -- 1 + ,null -- 2 + ,null -- 3 + ,null -- 4 + ,null -- 5 + ,null -- 6 + ,null -- 7 + ,null -- 8 + ,null -- 9 + ,null -- 10 + ,null -- 11 + ,null -- 12 + --,null -- 13 + --,null -- 14 + --,null -- 15 + from test_one_unique_value; + commit; """ - -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute(combine_output = True) +db = db_factory(init = init_sql, page_size = PAGE_SIZE) + +act = python_act('db', substitutions = [('[ \t]+', ' ')]) + +@pytest.mark.version('>=4') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + cur1=con.cursor() + cur2=con.cursor() + + cur1.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur1.fetchone()[0]) + + run_cpu_map = {} + for t_name in ('test_one_unique_value', 'test_null_in_all_rows'): + + fields_qry = f""" + select rf.rdb$field_name + from rdb$relation_fields rf + where rf.rdb$relation_name = upper('{t_name}') + order by rf.rdb$field_position + """ + cur1.execute(fields_qry) + fields_lst = [x[0].strip() for x in cur1.fetchall()] + + for f_name in fields_lst: + query1 = f'select count(*) from (select distinct {f_name} from {t_name})' + query2 = f'select count(distinct {f_name}) from {t_name}' + ps1 = cur1.prepare(query1) + ps2 = cur2.prepare(query2) + for c in (cur1, cur2): + cpu_usage_values = [] + psc = ps1 if c == cur1 else ps2 + for i in range(0, N_MEASURES): + fb_info_init = psutil.Process(fb_pid).cpu_times() + rs = c.execute(psc) + c.fetchall() + rs.close() + fb_info_curr = psutil.Process(fb_pid).cpu_times() + cpu_usage_values.append( max(fb_info_curr.user - fb_info_init.user, 0.000001) ) + + v = run_cpu_map.get( (t_name,f_name), [0,0,0, '','']) + if psc == ps1: + v[0] = median(cpu_usage_values) # 'select count(*) from (select distinct ...)' + else: + v[1] = median(cpu_usage_values) # 'select count(distinct ...) from ...' + v[2] = v[0] / v[1] + v[3] = query1 + v[4] = query2 + run_cpu_map[ (t_name,f_name) ] = v + + ps1.free() + ps2.free() + + poor_ratios_lst = [] + + #for k,v in run_cpu_map.items(): + # print(':::',k,':::') + # cpu_median_1, cpu_median_2, cpu_medians_ratio, query_1, query_2 = v + # # f'{ra=:12.4f}' + # msg = '\n'.join( + # ( f'{query_1=}' + # ,f'{query_2=}' + # ,f'{cpu_median_1=:12.4f} {cpu_median_2=:12.4f} {cpu_medians_ratio=:12.6f}' + # ) + # ) + # print(msg) + # print('-------------------------------------------------------------------------------------') + + + msg_prefix = 'CPU time medians ratio: ' + msg_expected = msg_prefix + 'EXPECTED.' + for k,v in run_cpu_map.items(): + if v[2] > MAX_RATIO: + poor_ratios_lst.append( '\n'.join( + ( 'query_1: ' + v[3] + ,'query_2: ' + v[4] + ,f'cpu_median_1: {v[0]:12.6f}' + ,f'cpu_median_2: {v[1]:12.6f}' + ,f'cpu_median_1 / cpu_median_2: {v[0]/v[1]:12.6f}' + ) + ) + ) + + if poor_ratios_lst: + print(f'{msg_prefix} /* perf_issue_tag */ UNEXPECTED. Following ratio(s) exceeds MAX_RATIO={MAX_RATIO}:') + for x in poor_ratios_lst: + print(x) + else: + print(msg_expected) + + + act.expected_stdout = msg_expected + act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout - From 8db3d1b57b8085b05a77a52db5d9f853627a2879 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 3 Dec 2024 12:08:59 +0300 Subject: [PATCH 0275/1064] Added/Updated tests\bugs\core_0214_test.py: Made MAX_RATIO different for Windows vs Linux. Increased its value on Linux: in some cases it can be more than 2.33 --- tests/bugs/core_0214_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0214_test.py b/tests/bugs/core_0214_test.py index 3e0e48d1..01a34cbc 100644 --- a/tests/bugs/core_0214_test.py +++ b/tests/bugs/core_0214_test.py @@ -33,7 +33,11 @@ Test for these datatypes will be added after fix of this ticked. Checked on Windiws (SS/CS): 6.0.0.535; 5.0.2.1569; 4.0.6.3169. + + [03.12.2024] pzotov + Made MAX_RATIO different for Windows vs Linux. Increased its value on Linux: in some cases it can be more than 2.33 """ +import os import psutil import time import pytest @@ -52,7 +56,7 @@ def median(lst): N_MEASURES = 11 PAGE_SIZE = 8192 N_ROWS_CNT= 100000 -MAX_RATIO = 2.0 +MAX_RATIO = 2.0 if os.name == 'nt' else 3.0 #---------------------------------------------------- # NOT yet used. See #8330: From eaa2d07ef280f43f4219fb2766fd15c037b82880 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 10 Dec 2024 18:00:07 +0300 Subject: [PATCH 0276/1064] Added/Updated tests\functional\replication\test_make_async_reinit_reliable.py: Checked on Windows, 5.0.2.1569. Temporary marked as to be SKIPPED on 4.x and 6.x until back- and front-port will be done. --- .../test_make_async_reinit_reliable.py | 688 ++++++++++++++++++ 1 file changed, 688 insertions(+) create mode 100644 tests/functional/replication/test_make_async_reinit_reliable.py diff --git a/tests/functional/replication/test_make_async_reinit_reliable.py b/tests/functional/replication/test_make_async_reinit_reliable.py new file mode 100644 index 00000000..71db380f --- /dev/null +++ b/tests/functional/replication/test_make_async_reinit_reliable.py @@ -0,0 +1,688 @@ +#coding:utf-8 + +""" +ID: replication.test_make_async_reinit_reliable +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8324 +TITLE: Make asynchronous replica re-initialization reliable #8324 +DESCRIPTION: + To reproduce problem from ticket one need to do following: + * create two tables ('test' and 'test2'), one of them must have quite long text column; + * add about one-two hundred rows in the 'test', see var. ADD_ROWS_INIT; + * start Tx on master (it will be OAT, see var. 'tx_oat') and: + ** add several thousands rows in the table 'test' (see var. ADD_ROWS_IN_OAT), but do NOT commit Tx; + ** stay idle (wait) until message with phrase "Segment... preserving (OAT: ... in segment ...)" + will appear in the replication log + * start one more Tx on master (see var 'tx_bef') and run some DML within this Tx against table 'TEST2', + with obtaining value of rdb$get_context('SYSTEM', 'REPLICATION_SEQUENCE') and store it for further + check (see var 'preserved_segment_no'). Commit this Tx. + Note: one need to use DIFFERENT table here. Do not use 'TEST'. + * Stay idle (wait) until replica becomes actual with master, i.e. table 'TEST2' will have same value + that was just used on master (see 'select count(*) from test2 where id = {TEST2_VALUE}') + * Change state of replica DB to full shutdown (in order to have ability to overwrite it further). + * Run on master: 'nacbkup -b 0' (see var. 'db_nbk0'). NOTE: this action increases ID of segment that + will be used for further writes. It is NOT so for command 'NBACKUP -L'. + * Handle just created .nbk0: run 'nbackup -SEQ -F', then set is as REPLICA and put fo FULL SHUTDOWN. + * Overwrite "old" replica with just created copy of master that has been prepared to serve as replica. + * Bring replica online; replication log will have following messages at this point: + BEFORE fix: + VERBOSE: Segment 2 (15729380 bytes) is replicated in 1.296s, preserving (OAT: 13 in segment 2) + VERBOSE: Segment 3 (646 bytes) is replicated in 0.013s, preserving (OAT: 13 in segment 2) + VERBOSE: Added 2 segment(s) to the queue + VERBOSE: Deleting segment 2 due to fast forward + VERBOSE: Deleting segment 3 due to fast forward + AFTER fix: + VERBOSE: Segment 2 (15729380 bytes) is replicated in 0.944s, preserving (OAT: 14 in segment 2) + VERBOSE: Added 1 segment(s) to the queue + VERBOSE: Added 2 segment(s) to the queue + VERBOSE: Segment 2 (15729380 bytes) is replayed in 1.438s, preserving (OAT: 14 in segment 2) + VERBOSE: Segment 3 (646 bytes) is replicated in 0.009s, preserving (OAT: 14 in segment 2) + VERBOSE: Added 2 segment(s) to the queue + ERROR: database shutdown + VERBOSE: Database sequence has been changed to 3, preparing for replication reset + * Master DB: do COMMIT for tx_oat. After this replication log following messages: + BEFORE fix: + VERBOSE: Added 1 segment(s) to the queue + VERBOSE: Resetting replication to continue from segment 4 + ERROR: Transaction 13 is not found + At segment 4, offset 48 + AFTER fix: + VERBOSE: Database sequence has been changed to 3, preparing for replication reset + VERBOSE: Added 2 segment(s) to the queue + VERBOSE: Database sequence has been changed to 3, preparing for replication reset + VERBOSE: Added 3 segment(s) to the queue + VERBOSE: Database sequence has been changed to 3, preparing for replication reset + VERBOSE: Segment 2 (15729380 bytes) is scanned in 0.006s, preserving (OAT: 14 in segment 2) + VERBOSE: Segment 3 (646 bytes) is scanned in 0.014s, preserving (OAT: 14 in segment 2) + VERBOSE: Resetting replication to continue from segment 4 (new OAT: 14 in segment 2) + VERBOSE: Segment 2 (15729380 bytes) is replayed in 1.343s, preserving (OAT: 14 in segment 2) + VERBOSE: Segment 3 (646 bytes) is replayed in 0.014s, preserving (OAT: 14 in segment 2) + VERBOSE: Segment 4 (321088 bytes) is replicated in 0.105s, deleting + VERBOSE: Deleting segment 2 as no longer needed + VERBOSE: Deleting segment 3 as no longer needed + * Check replication log that there is NO error message with text 'Transaction is not found' + * Stay idle (wait) until replica becomes actual with master, i.e. query 'select max(id) from test' + being issued on replica will return expected value = ADD_ROWS_INIT + ADD_ROWS_IN_OAT. + +NOTES: + [10.12.2024] pzotov + Checked on Windows, 5.0.2.1569 (SS/CS). + + :::: NOTE ::: + Temporary marked as to be SKIPPED on 4.x and 6.x until back- and front-port will be done. + + Great thanks to dimitr for suggestions about test implementation. +""" +import os +import shutil +import re +import locale +from difflib import unified_diff +from pathlib import Path +import datetime +import time + +import pytest +from firebird.qa import * +from firebird.driver import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +repl_settings = QA_GLOBALS['replication'] + +MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG = int(repl_settings['max_time_for_wait_segment_in_log']) +MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) + +MAIN_DB_ALIAS = repl_settings['main_db_alias'] +REPL_DB_ALIAS = repl_settings['repl_db_alias'] +RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) + +db_main = db_factory( filename = '#' + MAIN_DB_ALIAS, do_not_create = True, do_not_drop = True) +db_repl = db_factory( filename = '#' + REPL_DB_ALIAS, do_not_create = True, do_not_drop = True) + +# Where we want to store result of 'nbackup -b 0 ': +db_nbk0 = temp_file('gh_8324_tmp.nbk0') + +substitutions = [('Start removing objects in:.*', 'Start removing objects'), + ('Finish. Total objects removed: [1-9]\\d*', 'Finish. Total objects removed'), + ('.* CREATE DATABASE .*', ''), + ('[\t ]+', ' '), + ('FOUND message about replicated segment N .*', 'FOUND message about replicated segment')] + +act_db_main = python_act('db_main', substitutions=substitutions) +act_db_repl = python_act('db_repl', substitutions=substitutions) + +#-------------------------------------------- + +def cleanup_folder(p): + # Removed all files and subdirs in the folder

+ # Used for cleanup and when replication must be reset + # in case when any error occurred during test execution. + assert os.path.dirname(p) != p, f"@@@ ABEND @@@ CAN NOT operate in the file system root directory. Check your code!" + + for root, dirs, files in os.walk(p): + for f in files: + # ::: NB ::: 22.12.2023. + # We have to expect that attempt to delete of GUID and (maybe) archived segments can FAIL with + # PermissionError: [WinError 32] The process cannot ... used by another process: /path/to/{GUID} + # Also, we have to skip exception if file (segment) was just deleted by engine + try: + Path(root +'/' + f).unlink(missing_ok = True) + except PermissionError as x: + pass + + for d in dirs: + shutil.rmtree(os.path.join(root, d), ignore_errors = True) + + return os.listdir(p) + +#-------------------------------------------- + +def reset_replication(act_db_main, act_db_repl, db_main_file, db_repl_file): + out_reset = '' + failed_shutdown_db_map = {} # K = 'db_main', 'db_repl'; V = error that occurred when we attempted to change DB state to full shutdown (if it occurred) + + with act_db_main.connect_server() as srv: + + # !! IT IS ASSUMED THAT REPLICATION FOLDERS ARE IN THE SAME DIR AS !! + # DO NOT use 'a.db.db_path' for ALIASED database! + # It will return '.' rather than full path+filename. + + repl_root_path = Path(db_main_file).parent + repl_jrn_sub_dir = repl_settings['journal_sub_dir'] + repl_arc_sub_dir = repl_settings['archive_sub_dir'] + + for f in (db_main_file, db_repl_file): + # Method db.drop() changes LINGER to 0, issues 'delete from mon$att' with suppressing exceptions + # and calls 'db.drop_database()' (also with suppressing exceptions). + # We change DB state to FULL SHUTDOWN instead of call action.db.drop() because + # this is more reliable (it kills all attachments in all known cases and does not use mon$ table) + # + try: + srv.database.shutdown(database = f, mode = ShutdownMode.FULL, method = ShutdownMethod.FORCED, timeout = 0) + + # REMOVE db file from disk: we can safely assume that this can be done because DB in full shutdown state. + ########################### + os.unlink(f) + except DatabaseError as e: + failed_shutdown_db_map[ f ] = e.__str__() + + + # Clean folders repl_journal and repl_archive: remove all files from there. + # NOTE: test must NOT raise unrecoverable error if some of files in these folders can not be deleted. + # Rather, this must be displayed as diff and test must be considered as just failed. + for p in (repl_jrn_sub_dir,repl_arc_sub_dir): + + remained_files = cleanup_folder(repl_root_path/p) + + if remained_files: + out_reset += '\n'.join( (f"Directory '{str(repl_root_path/p)}' remains non-empty. Could not delete file(s):", '\n'.join(remained_files)) ) + + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxx r e c r e a t e d b _ m a i n a n d d b _ r e p l xxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + for a in (act_db_main,act_db_repl): + d = a.db.db_path + failed_shutdown_msg = failed_shutdown_db_map.get( str(d), '' ) + if failed_shutdown_msg: + # we could NOT change state of this database to full shutdown --> we must NOT recreate it. + # Accumulate error messages in OUT arg (for displaying as diff): + # + out_reset += '\n'.join( failed_shutdown_msg ) + else: + try: + dbx = create_database(str(d), user = a.db.user) + dbx.close() + with a.connect_server() as srv: + srv.database.set_write_mode(database = d, mode = DbWriteMode.ASYNC) + srv.database.set_sweep_interval(database = d, interval = 0) + if a == act_db_repl: + srv.database.set_replica_mode(database = d, mode = ReplicaMode.READ_ONLY) + else: + with a.db.connect() as con: + con.execute_immediate('alter database enable publication') + con.execute_immediate('alter database include all to publication') + con.commit() + except DatabaseError as e: + out_reset += e.__str__() + + # Must remain EMPTY: + #################### + return out_reset + +#-------------------------------------------- + +def watch_repl_log_pattern( act_db_main: Action, pattern_to_check, replold_lines, max_allowed_time_for_wait, consider_found_as_unexpected = False): + + replication_log = act_db_main.home_dir / 'replication.log' + + result = '' + found_required_message = False + found_required_line = '' + t0 = time.time() + for i in range(0,max_allowed_time_for_wait): + + time.sleep(1) + + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + + for k,d in enumerate(diff_data): + if pattern_to_check.search(d): + found_required_message = True + break + + if found_required_message: + break + t1 = time.time() + if not consider_found_as_unexpected and not found_required_message or consider_found_as_unexpected and found_required_message: + # ACHTUNG! This looks weird but we have to either re-read replication log now or wait at least seconds + # if we want to see FULL (actual) content of this log! Otherwise last part of log will be missed. I have no explanations for that :( + repllog_diff = '' + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + repllog_diff = '\n'.join( ( ('%4d ' %i) + r.rstrip() for i,r in enumerate(diff_data) ) ) + + if consider_found_as_unexpected: + unexp_msg = f"UNEXPECTED outcome: pattern '{pattern_to_check.pattern}' must not occur in log but was ENCOUNTERED there for {int(t1-t0)} seconds." + else: + unexp_msg = f"MISSED outcome: pattern '{pattern_to_check.pattern}' was NOT FOUND for {int(t1-t0)} seconds." + + result = '\n'.join( (unexp_msg, 'replication log diff:', repllog_diff) ) + + return result + +#-------------------------------------------- + +def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + + retcode = 1; + ready_to_check = False + if ddl_ready_query: + with a.db.connect(no_db_triggers = True) as con: + with con.cursor() as cur: + for i in range(0,max_allowed_time_for_wait): + cur.execute(ddl_ready_query) + count_actual = cur.fetchone() + if count_actual: + ready_to_check = True + break + else: + con.rollback() + time.sleep(1) + else: + ready_to_check = True + + if not ready_to_check: + print( f'UNEXPECTED. Query to verify DDL completion did not return any rows for {max_allowed_time_for_wait} seconds.' ) + print('Query:') + print(ddl_ready_query) + + return + + final_check_pass = False + if isql_check_script: + retcode = 0 + for i in range(max_allowed_time_for_wait): + a.reset() + a.expected_stdout = replica_expected_out + a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) + + if a.return_code: + # "Token unknown", "Name longer than database column size" etc: we have to + # immediately break from this loop because isql_check_script is incorrect! + break + + if a.clean_stdout == a.clean_expected_stdout: + final_check_pass = True + break + if i < max_allowed_time_for_wait-1: + time.sleep(1) + + if not final_check_pass: + print(f'UNEXPECTED. Final check query did not return expected dataset for {max_allowed_time_for_wait} seconds.') + print('Final check query:') + print(isql_check_script) + print('Expected output:') + print(a.clean_expected_stdout) + print('Actual output:') + print(a.clean_stdout) + print(f'ISQL return_code={a.return_code}') + print(f'Waited for {i} seconds') + + a.reset() + + else: + final_check_pass = True + + return + +#-------------------------------------------- + +def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): + + # return initial state of master DB: + # remove all DB objects (tables, views, ...): + # + db_main_meta, db_repl_meta = '', '' + for a in (act_db_main,act_db_repl): + if a == act_db_main: + sql_clean = (a.files_dir / 'drop-all-db-objects.sql').read_text() + a.expected_stdout = """ + Start removing objects + Finish. Total objects removed + """ + a.isql(switches=['-q', '-nod'], input = sql_clean, combine_output = True) + + if a.clean_stdout == a.clean_expected_stdout: + a.reset() + else: + print(a.clean_expected_stdout) + a.reset() + break + + # NB: one need to remember that rdb$system_flag can be NOT ONLY 1 for system used objects! + # For example, it has value =3 for triggers that are created to provide CHECK-constraints, + # Custom DB objects always have rdb$system_flag = 0 (or null for some very old databases). + # We can be sure that there are no custom DB objects if following query result is NON empty: + # + ddl_ready_query = """ + select 1 + from rdb$database + where NOT exists ( + select custom_db_object_flag + from ( + select rt.rdb$system_flag as custom_db_object_flag from rdb$triggers rt + UNION ALL + select rt.rdb$system_flag from rdb$relations rt + UNION ALL + select rt.rdb$system_flag from rdb$functions rt + UNION ALL + select rt.rdb$system_flag from rdb$procedures rt + UNION ALL + select rt.rdb$system_flag from rdb$exceptions rt + UNION ALL + select rt.rdb$system_flag from rdb$fields rt + UNION ALL + select rt.rdb$system_flag from rdb$collations rt + UNION ALL + select rt.rdb$system_flag from rdb$generators rt + UNION ALL + select rt.rdb$system_flag from rdb$roles rt + UNION ALL + select rt.rdb$system_flag from rdb$auth_mapping rt + UNION ALL + select 1 from sec$users s + where upper(s.sec$user_name) <> 'SYSDBA' + ) t + where coalesce(t.custom_db_object_flag,0) = 0 + ) + """ + + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + print(capsys.readouterr().out) + + db_main_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + else: + db_repl_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + + if RUN_SWEEP_AT_END: + # Following sweep was mandatory during 2021...2022. Problem was fixed: + # * for FB 4.x: 26-jan-2023, commit 2ed48a62c60c029cd8cb2b0c914f23e1cb56580a + # * for FB 5.x: 20-apr-2023, commit 5af209a952bd2ec3723d2c788f2defa6b740ff69 + # (log message: 'Avoid random generation of field IDs, respect the user-specified order instead'). + # Until this problem was solved, subsequent runs of this test caused to fail with: + # 'ERROR: Record format with length NN is not found for table TEST' + # + a.gfix(switches=['-sweep', a.db.dsn]) + + # Final point: metadata must become equal: + # + diff_meta = ''.join(unified_diff( \ + [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], + [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) + ) + # Must be EMPTY: + print(diff_meta) + +#-------------------------------------------- + +def get_repl_log(act_db_main: Action): + replication_log = act_db_main.home_dir / 'replication.log' + rlog_lines = [] + with open(replication_log, 'r') as f: + rlog_lines = f.readlines() + + return rlog_lines + +#-------------------------------------------- + +@pytest.mark.replication +@pytest.mark.version('>=5.0.1,<6') +def test_1(act_db_main: Action, act_db_repl: Action, db_nbk0: Path, capsys): + + FLD_WIDTH = 500 + ADD_ROWS_INIT = 100 + ADD_ROWS_IN_OAT = 30000 + TEST2_VALUE = -2147483648 + + # Map for storing mnemonas and details for every FAILED step: + run_errors_map = {} + + # Obtain full path + filename for DB_MAIN and DB_REPL aliases. + # NOTE: we must NOT use 'a.db.db_path' for ALIASED databases! + # It will return '.' rather than full path+filename. + # Use only con.info.name for that! + # + db_info = {} + for a in (act_db_main, act_db_repl): + with a.db.connect() as con: + db_info[a, 'db_full_path'] = con.info.name + + sql_init = f""" + set bail on; + set wng off; + recreate table test ( + id int generated by default as identity constraint test_pk primary key + ,dts timestamp default 'now' + ,trn bigint default current_transaction + ,s varchar({FLD_WIDTH}) unique using index test_f01_unq + ); + + recreate table test2 ( + id int generated by default as identity constraint test2_pk primary key + ,dts timestamp default 'now' + ,trn bigint default current_transaction + ,s varchar({FLD_WIDTH}) unique using index test2_f01_unq + ); + commit; + + insert into test(s) select lpad( '', {FLD_WIDTH}, uuid_to_char(gen_uuid()) ) from rdb$types rows {ADD_ROWS_INIT}; + commit; + + recreate table t_completed(id int primary key); + commit; + """ + act_db_main.isql(switches=['-q'], input = sql_init, combine_output = True) + run_errors_map['out_prep_ddl'] = act_db_main.clean_stdout + act_db_main.reset() + + if max(v.strip() for v in run_errors_map.values()): + # Some problem raised during init_sql execution + pass + else: + # Query to be used for check that all DB objects present in replica (after last DML statement completed on master DB): + ddl_ready_query = "select 1 from rdb$relations where rdb$relation_name = upper('t_completed')" + ##################################################################### + ### WAIT UNTIL REPLICA GET SEGMENT(S) WITH INITIAL DDL AND DATA ### + ##################################################################### + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + run_errors_map['out_repl_ddl'] = capsys.readouterr().out + + if max(v.strip() for v in run_errors_map.values()): + # Some problem raised with delivering DDL changes to replica + pass + else: + + with act_db_main.db.connect() as con: + preserved_segment_no = -1 + + tp_oat = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = 0) + tx_oat = con.transaction_manager(tp_oat) + cur_oat = tx_oat.cursor() + + tx_oat.begin() + replold_lines = get_repl_log(act_db_main) + + try: + cur_oat.execute(f"insert /* trace_tag OAT */ into test(s) select lpad('', {FLD_WIDTH}, uuid_to_char(gen_uuid())) from rdb$types,rdb$types rows {ADD_ROWS_IN_OAT} returning id") + cur_oat.fetchall() # mandatory! + except DatabaseError as e: + run_errors_map['main_oat_init_err'] = e.__str__() + + if max(v.strip() for v in run_errors_map.values()): + # Some problem was in just executed OAT-statement + pass + else: + ############################################################## + ### CHECK REPL.LOG: WAITING FOR "PRESERVING OAT" MESSAGE ### + ############################################################## + # VERBOSE: Segment 2 (11534562 bytes) is replicated in 0.934s, preserving (OAT: 10 in segment 2) + pattern_to_check = re.compile( r'preserving \(oat:\s+\d+\s+in\s+segment\s+\d+', re.IGNORECASE ) + run_errors_map['repl_preserve_oat_err'] = watch_repl_log_pattern( act_db_main, pattern_to_check, replold_lines, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG) + + if max(v.strip() for v in run_errors_map.values()): + # Timeout expired: message "Segment ... preserving (OAT: ... in segment ...)" did not appeared + # in replication log for seconds. + pass + else: + + ############################################### + ### MASTER: RUN DML BEFORE 'NBACKUP -B 0' ### + ############################################### + # tp_wrk = tpb(isolation = Isolation.READ_COMMITTED_READ_CONSISTENCY, lock_timeout = 3) # ?!?! check trace !!! + tp_bef = tpb(isolation = Isolation.READ_COMMITTED, lock_timeout = 3) + tx_bef = con.transaction_manager(tp_bef) + cur_bef = tx_bef.cursor() + try: + tx_bef.begin() + cur_bef.execute(f"insert /* trace_tag before creating nbk-0 */ into test2(id) values(?) returning rdb$get_context('SYSTEM', 'REPLICATION_SEQUENCE')", (TEST2_VALUE,)) + + # If returned value of rdb$get_context('SYSTEM', 'REPLICATION_SEQUENCE') is then + # message in replication log contains this number PLUS 1, e.g. (for REPLICATION_SEQUENCE = 1): + # "Segment 2 (11534562 bytes) is replicated in 0.934s, preserving (OAT: 10 in segment 2)" + # We store this result in order to check further content of replication log that this + # segment was eventuially deleted (this will mean SUCCESSFUL finish of test): + # + preserved_segment_no = int(cur_bef.fetchone()[0]) + 1 + tx_bef.commit() + except DatabaseError as e: + run_errors_map['main_dml_afte_nbk0_err'] = e.__str__() + + if max(v.strip() for v in run_errors_map.values()): + # Some problem was in just executed statement + pass + else: + ############################################## + ### WAIT UNTIL REPLICA DB BECOMES ACTUAL ### + ############################################## + # ( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + chk_bef_sql = f'set heading off;select count(*) from test2 where id = {TEST2_VALUE};' + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query = '', isql_check_script = chk_bef_sql, replica_expected_out = '1' ) + + # Must be EMPTY: + run_errors_map['repl_chk_addi_data_err'] = capsys.readouterr().out + + if max(v.strip() for v in run_errors_map.values()): + # Timeout expired: expected data did not appear in replica DB for seconds. + pass + else: + ################################################ + ### REPLICA: CHANGE STATE TO FULL SHUTDOWN ### + ################################################ + act_db_repl.gfix(switches=['-shut', 'full', '-force', '0', act_db_repl.db.dsn], io_enc = locale.getpreferredencoding(), combine_output = True ) + run_errors_map['repl_full_shutdown_err'] = act_db_repl.stdout + act_db_repl.reset() + + if max(v.strip() for v in run_errors_map.values()): + pass + else: + ########################################## + ### M A S T E R: M A K E N B K 0 ## + ########################################## + # DO NOT use 'combine_output = True' here: nbackup produces non-empty output when successfully completes. + act_db_main.nbackup( switches = ['-b', '0', act_db_main.db.dsn, db_nbk0], io_enc = locale.getpreferredencoding(), combine_output = False ) + run_errors_map['main_create_nbk0_err'] = act_db_main.stderr + act_db_main.reset() + + if max(v.strip() for v in run_errors_map.values()): + # Some errors occurres during 'nbackup -b 0 db_main_alias ...' + pass + else: + ############################################################################################## + ### NBK0: FIXUP, SET AS REPLICA, CHANGE STATE TO FULL SHUTDOWN, MOVE TO OLD 'DB_REPL' ### + ############################################################################################## + try: + act_db_repl.nbackup(switches = ['-SEQ', '-F', str(db_nbk0)], combine_output = True, io_enc = locale.getpreferredencoding()) + # act_db_main.svcmgr(switches=['action_nfix', 'dbname', str(db_nbk0)], io_enc = locale.getpreferredencoding()) + with act_db_main.connect_server() as srv: + #srv.database.nfix_database(database = db_nbk0) --> "Internal error when using clumplet API: attempt to store data in dataless clumplet" // see also: core_5085_test.py + srv.database.set_replica_mode(database = db_nbk0, mode = ReplicaMode.READ_ONLY) + srv.database.shutdown(database = db_nbk0, mode = ShutdownMode.FULL, method = ShutdownMethod.FORCED, timeout = 0) + except DatabaseError as e: + run_errors_map['nbk0_make_new_replica_err'] = e.__str__() + + if max(v.strip() for v in run_errors_map.values()): + pass + else: + + ################################## + ### OVERWRITE OLD REPLICA ### + ################################## + shutil.move(db_nbk0, db_info[act_db_repl,'db_full_path']) + + ################################## + ### REPLICA: BRING ONLINE ### + ################################## + act_db_repl.gfix(switches=['-online', act_db_repl.db.dsn], io_enc = locale.getpreferredencoding(), combine_output = True ) + run_errors_map['repl_bring_online_err'] = act_db_repl.stdout + act_db_repl.reset() + + replold_lines = get_repl_log(act_db_main) + if max(v.strip() for v in run_errors_map.values()): + pass + else: + ############################################## + ### MASTER: FINAL ACTION WITHIN TX = OAT ### + ############################################## + try: + tx_oat.commit() + except DatabaseError as e: + run_errors_map['main_oat_fini_err'] = e.__str__() + + if max(v.strip() for v in run_errors_map.values()): + pass + else: + + ############################################################################ + ### CHECK REPL.LOG: WAITING FOR "Transaction is not found" MESSAGE ### + ############################################################################ + # Before fix: "ERROR: Transaction 13 is not found" appeared in the repl log at thios point. + pattern_to_check = re.compile( r'Error:\s+Transaction\s+\d+\s+(is\s+)?not\s+found', re.IGNORECASE ) + run_errors_map['repl_tx_not_found_err'] = watch_repl_log_pattern( act_db_main, pattern_to_check, replold_lines, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG, consider_found_as_unexpected = True) + + if max(v.strip() for v in run_errors_map.values()): + pass + else: + ############################################## + ### WAIT UNTIL REPLICA DB BECOMES ACTUAL ### + ############################################## + # ( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + chk_oat_sql = 'set heading off;select max(id) from test;' + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query = '', isql_check_script = chk_oat_sql, replica_expected_out = str(ADD_ROWS_INIT+ADD_ROWS_IN_OAT) ) + # Must be EMPTY: + run_errors_map['repl_chk_fini_err'] = capsys.readouterr().out + + if max(v.strip() for v in run_errors_map.values()): + pass + else: + ####################################################################################### + ### CHECK REPL.LOG: WAITING FOR "DELETING SEGMENT {} AS NO LONGER NEEDED" MESSAGE ### + ####################################################################################### + # VERBOSE: Deleting segment 2 as no longer needed + # NB: before fix message was: "VERBOSE: Deleting segment 2 due to fast forward" + pattern_to_check = re.compile( r'VERBOSE:\s+Deleting\s+segment\s+%d\s+as\s+no\s+longer\s+needed' % preserved_segment_no, re.IGNORECASE ) + run_errors_map['repl_deleted_oat_segm'] = watch_repl_log_pattern( act_db_main, pattern_to_check, replold_lines, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG) + + if max(v.strip() for v in run_errors_map.values()): + # We had a problem in some of previous steps. + # First, we have to RECREATE both master and slave databases + # (otherwise further execution of this test or other replication-related tests most likely will fail): + run_errors_map['out_reset'] = reset_replication(act_db_main, act_db_repl, db_info[act_db_main,'db_full_path'], db_info[act_db_repl,'db_full_path']) + else: + drop_db_objects(act_db_main, act_db_repl, capsys) + # Must be EMPTY: + run_errors_map['out_drop'] = capsys.readouterr().out + + if max(v.strip() for v in run_errors_map.values()): + print(f'Problem(s) detected, check run_errors_map:') + for k,v in run_errors_map.items(): + if v.strip(): + print(k,':') + print(v.strip()) + print('-' * 40) + + assert '' == capsys.readouterr().out From ea82a1e9191fef199f644812d2332710081e94cf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 10 Dec 2024 18:35:52 +0300 Subject: [PATCH 0277/1064] Added/Updated tests\functional\replication\test_make_async_reinit_reliable.py: removed limitation for verions: execution allowed since 4.0.6. Adjusted comments. --- .../test_make_async_reinit_reliable.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/functional/replication/test_make_async_reinit_reliable.py b/tests/functional/replication/test_make_async_reinit_reliable.py index 71db380f..e441360d 100644 --- a/tests/functional/replication/test_make_async_reinit_reliable.py +++ b/tests/functional/replication/test_make_async_reinit_reliable.py @@ -65,11 +65,11 @@ NOTES: [10.12.2024] pzotov - Checked on Windows, 5.0.2.1569 (SS/CS). - - :::: NOTE ::: - Temporary marked as to be SKIPPED on 4.x and 6.x until back- and front-port will be done. - + Confirmed bug on 5.0.2.1567-9fbd574 (16.11.2024 20:15). + Checked on Windows: + 5.0.2.1569-684bb87 (27.11.2024 20:40). + 4.0.6.3170-cc44002 (10.12.2024 07:02) + 6.0.0.548-a8c5b9f (10.12.2024 10:13) Great thanks to dimitr for suggestions about test implementation. """ import os @@ -429,7 +429,7 @@ def get_repl_log(act_db_main: Action): #-------------------------------------------- @pytest.mark.replication -@pytest.mark.version('>=5.0.1,<6') +@pytest.mark.version('>=4.0.6') def test_1(act_db_main: Action, act_db_repl: Action, db_nbk0: Path, capsys): FLD_WIDTH = 500 @@ -508,8 +508,9 @@ def test_1(act_db_main: Action, act_db_repl: Action, db_nbk0: Path, capsys): replold_lines = get_repl_log(act_db_main) try: - cur_oat.execute(f"insert /* trace_tag OAT */ into test(s) select lpad('', {FLD_WIDTH}, uuid_to_char(gen_uuid())) from rdb$types,rdb$types rows {ADD_ROWS_IN_OAT} returning id") - cur_oat.fetchall() # mandatory! + cur_oat.execute(f"insert /* trace_tag OAT */ into test(s) select lpad('', {FLD_WIDTH}, uuid_to_char(gen_uuid())) from rdb$types,rdb$types rows {ADD_ROWS_IN_OAT}") + cur_oat.execute('select max(id) from test') + cur_oat.fetchone() except DatabaseError as e: run_errors_map['main_oat_init_err'] = e.__str__() From bc691dd2aa22a959730f2fe7fd508eef3c97b8d8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 11 Dec 2024 12:30:24 +0300 Subject: [PATCH 0278/1064] Updated tests\bugs\gh_7675_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_7675_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_7675_test.py b/tests/bugs/gh_7675_test.py index 253fc4b5..27627c4a 100644 --- a/tests/bugs/gh_7675_test.py +++ b/tests/bugs/gh_7675_test.py @@ -72,7 +72,7 @@ 07: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 : name: OBJECT_NAME alias: OBJECT_NAME - 08: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + 08: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 : name: ALIAS alias: ALIAS 09: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 From 7afd1647d0113b32a33c1f92e9997ade653b2f8d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Dec 2024 01:20:30 +0300 Subject: [PATCH 0279/1064] Added/Updated tests\functional\replication\test_grantor_not_changes_in_replica_if_owner_not_sysdba.py: Checked on 6.0.0.552, 5.0.2.1569, 4.0.6.3170. --- ..._changes_in_replica_if_owner_not_sysdba.py | 491 ++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py diff --git a/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py b/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py new file mode 100644 index 00000000..38d834b6 --- /dev/null +++ b/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py @@ -0,0 +1,491 @@ +#coding:utf-8 + +""" +ID: replication.test_grantor_not_changes_in_replica_if_owner_not_sysdba +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8058 +TITLE: DDL-Changes in replication does not set the correct grantor +DESCRIPTION: + Test creates user with admin rights (see 'db_main_owner') and calls 'reset_replication' function in order + to re-create db_main database with new OWNER = , i.e. it must differ from SYSDBA. + Then it does actions described in the ticket. + Final REVOKE command being issued against db_main must apply also in db_repl, w/o error. + Test verifies that by checking result of query: + select 1 as db_repl_privilege_unexp_remains from rdb$database + where exists ( + select 1 from rdb$user_privileges p where p.rdb$relation_name = upper('test') and p.rdb$privilege = upper('D') + ); + Outcome of this query on REPLICA database must become empty for no more than MAX_TIME_FOR_WAIT_DATA_IN_REPLICA seconds. + Otherwise test is considered as failed. + + We have to restore owner = SYSDBA for db_main, so we call 'reset_replication' function second time at final point. + +NOTES: + [15.12.2024] pzotov + Test execution time is about 7...8 seconds (for snapshots that have fix). + + Confirmed bug on 6.0.0.299, 5.0.1.1371, 4.0.5.3082 + Checked on 6.0.0.552, 5.0.2.1569, 4.0.6.3170. +""" +import os +import shutil +import re +import locale +from difflib import unified_diff +from pathlib import Path +import datetime +import time + +import pytest +from firebird.qa import * +from firebird.driver import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +repl_settings = QA_GLOBALS['replication'] + +MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG = int(repl_settings['max_time_for_wait_segment_in_log']) +MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) + +MAIN_DB_ALIAS = repl_settings['main_db_alias'] +REPL_DB_ALIAS = repl_settings['repl_db_alias'] +RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) + + +db_main = db_factory( filename = '#' + MAIN_DB_ALIAS, do_not_create = True, do_not_drop = True) +db_repl = db_factory( filename = '#' + REPL_DB_ALIAS, do_not_create = True, do_not_drop = True) + +db_main_owner = user_factory('db_main', name = 'tmp_gh_8058', password = '456', admin = True) + +substitutions = [('Start removing objects in:.*', 'Start removing objects'), + ('Finish. Total objects removed: [1-9]\\d*', 'Finish. Total objects removed'), + ('.* CREATE DATABASE .*', ''), + ('[\t ]+', ' '), + ('FOUND message about replicated segment N .*', 'FOUND message about replicated segment')] + +act_db_main = python_act('db_main', substitutions=substitutions) +act_db_repl = python_act('db_repl', substitutions=substitutions) + +#-------------------------------------------- + +def cleanup_folder(p): + # Removed all files and subdirs in the folder

+ # Used for cleanup and when replication must be reset + # in case when any error occurred during test execution. + assert os.path.dirname(p) != p, f"@@@ ABEND @@@ CAN NOT operate in the file system root directory. Check your code!" + + for root, dirs, files in os.walk(p): + for f in files: + # ::: NB ::: 22.12.2023. + # We have to expect that attempt to delete of GUID and (maybe) archived segments can FAIL with + # PermissionError: [WinError 32] The process cannot ... used by another process: /path/to/{GUID} + # Also, we have to skip exception if file (segment) was just deleted by engine + try: + Path(root +'/' + f).unlink(missing_ok = True) + except PermissionError as x: + pass + + for d in dirs: + shutil.rmtree(os.path.join(root, d), ignore_errors = True) + + return os.listdir(p) + +#-------------------------------------------- + +# ::: NB ::: +# THIS FUNCTION HAS ADDITIONAL INPUT PARAMETER: 'db_main_owner' +# +def reset_replication(act_db_main: Action, act_db_repl: Action, db_main_file, db_repl_file, db_main_owner: User = None): + out_reset = '' + failed_shutdown_db_map = {} # K = 'db_main', 'db_repl'; V = error that occurred when we attempted to change DB state to full shutdown (if it occurred) + + with act_db_main.connect_server() as srv: + + # !! IT IS ASSUMED THAT REPLICATION FOLDERS ARE IN THE SAME DIR AS !! + # DO NOT use 'a.db.db_path' for ALIASED database! + # It will return '.' rather than full path+filename. + + repl_root_path = Path(db_main_file).parent + repl_jrn_sub_dir = repl_settings['journal_sub_dir'] + repl_arc_sub_dir = repl_settings['archive_sub_dir'] + + for f in (db_main_file, db_repl_file): + # Method db.drop() changes LINGER to 0, issues 'delete from mon$att' with suppressing exceptions + # and calls 'db.drop_database()' (also with suppressing exceptions). + # We change DB state to FULL SHUTDOWN instead of call action.db.drop() because + # this is more reliable (it kills all attachments in all known cases and does not use mon$ table) + # + try: + srv.database.shutdown(database = f, mode = ShutdownMode.FULL, method = ShutdownMethod.FORCED, timeout = 0) + + # REMOVE db file from disk: we can safely assume that this can be done because DB in full shutdown state. + ########################### + os.unlink(f) + except DatabaseError as e: + failed_shutdown_db_map[ f ] = e.__str__() + + + # Clean folders repl_journal and repl_archive: remove all files from there. + # NOTE: test must NOT raise unrecoverable error if some of files in these folders can not be deleted. + # Rather, this must be displayed as diff and test must be considered as just failed. + for p in (repl_jrn_sub_dir,repl_arc_sub_dir): + + remained_files = cleanup_folder(repl_root_path/p) + + if remained_files: + out_reset += '\n'.join( (f"Directory '{str(repl_root_path/p)}' remains non-empty. Could not delete file(s):", '\n'.join(remained_files)) ) + + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxx r e c r e a t e d b _ m a i n a n d d b _ r e p l xxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + for a in (act_db_main,act_db_repl): + d = a.db.db_path + failed_shutdown_msg = failed_shutdown_db_map.get( str(d), '' ) + if failed_shutdown_msg: + # we could NOT change state of this database to full shutdown --> we must NOT recreate it. + # Accumulate error messages in OUT arg (for displaying as diff): + # + out_reset += '\n'.join( failed_shutdown_msg ) + else: + try: + if db_main_owner and a == act_db_main: + dbx = create_database( str(d), user = db_main_owner.name, password = db_main_owner.password ) + else: + dbx = create_database( str(d), user = a.db.user, password = a.db.password ) + dbx.close() + with a.connect_server() as srv: + srv.database.set_write_mode(database = d, mode = DbWriteMode.ASYNC) + srv.database.set_sweep_interval(database = d, interval = 0) + if a == act_db_repl: + srv.database.set_replica_mode(database = d, mode = ReplicaMode.READ_ONLY) + else: + with a.db.connect() as con: + con.execute_immediate(f'alter database enable publication') + con.execute_immediate('alter database include all to publication') + con.commit() + except DatabaseError as e: + out_reset += e.__str__() + + # Must remain EMPTY: + #################### + return out_reset + +#-------------------------------------------- + +def watch_repl_log_pattern( act_db_main: Action, pattern_to_check, replold_lines, max_allowed_time_for_wait, consider_found_as_unexpected = False): + + replication_log = act_db_main.home_dir / 'replication.log' + + result = '' + found_required_message = False + found_required_line = '' + t0 = time.time() + for i in range(0,max_allowed_time_for_wait): + + time.sleep(1) + + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + + for k,d in enumerate(diff_data): + if pattern_to_check.search(d): + found_required_message = True + break + + if found_required_message: + break + t1 = time.time() + if not consider_found_as_unexpected and not found_required_message or consider_found_as_unexpected and found_required_message: + # ACHTUNG! This looks weird but we have to either re-read replication log now or wait at least seconds + # if we want to see FULL (actual) content of this log! Otherwise last part of log will be missed. I have no explanations for that :( + repllog_diff = '' + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + repllog_diff = '\n'.join( ( ('%4d ' %i) + r.rstrip() for i,r in enumerate(diff_data) ) ) + + if consider_found_as_unexpected: + unexp_msg = f"UNEXPECTED outcome: pattern '{pattern_to_check.pattern}' must not occur in log but was ENCOUNTERED there for {int(t1-t0)} seconds." + else: + unexp_msg = f"MISSED outcome: pattern '{pattern_to_check.pattern}' was NOT FOUND for {int(t1-t0)} seconds." + + result = '\n'.join( (unexp_msg, 'replication log diff:', repllog_diff) ) + + return result + +#-------------------------------------------- + +def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + + retcode = 1; + ready_to_check = False + if ddl_ready_query: + with a.db.connect(no_db_triggers = True) as con: + with con.cursor() as cur: + for i in range(0,max_allowed_time_for_wait): + cur.execute(ddl_ready_query) + count_actual = cur.fetchone() + if count_actual: + ready_to_check = True + break + else: + con.rollback() + time.sleep(1) + else: + ready_to_check = True + + if not ready_to_check: + print( f'UNEXPECTED. Query to verify DDL completion did not return any rows for {max_allowed_time_for_wait} seconds.' ) + print('Query:') + print(ddl_ready_query) + + return + + final_check_pass = False + if isql_check_script: + retcode = 0 + for i in range(max_allowed_time_for_wait): + a.reset() + a.expected_stdout = replica_expected_out + a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) + + if a.return_code: + # "Token unknown", "Name longer than database column size" etc: we have to + # immediately break from this loop because isql_check_script is incorrect! + break + + if a.clean_stdout == a.clean_expected_stdout: + final_check_pass = True + break + if i < max_allowed_time_for_wait-1: + time.sleep(1) + + if not final_check_pass: + print(f'UNEXPECTED. Final check query did not return expected dataset for {max_allowed_time_for_wait} seconds.') + print('Final check query:') + print(isql_check_script) + print('Expected output:') + print(a.clean_expected_stdout) + print('Actual output:') + print(a.clean_stdout) + print(f'ISQL return_code={a.return_code}') + print(f'Waited for {i} seconds') + + a.reset() + + else: + final_check_pass = True + + return + +#-------------------------------------------- + +def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): + + # return initial state of master DB: + # remove all DB objects (tables, views, ...): + # + db_main_meta, db_repl_meta = '', '' + for a in (act_db_main,act_db_repl): + if a == act_db_main: + sql_clean = (a.files_dir / 'drop-all-db-objects.sql').read_text() + a.expected_stdout = """ + Start removing objects + Finish. Total objects removed + """ + a.isql(switches=['-q', '-nod'], input = sql_clean, combine_output = True) + + if a.clean_stdout == a.clean_expected_stdout: + a.reset() + else: + print(a.clean_expected_stdout) + a.reset() + break + + # NB: one need to remember that rdb$system_flag can be NOT ONLY 1 for system used objects! + # For example, it has value =3 for triggers that are created to provide CHECK-constraints, + # Custom DB objects always have rdb$system_flag = 0 (or null for some very old databases). + # We can be sure that there are no custom DB objects if following query result is NON empty: + # + ddl_ready_query = """ + select 1 + from rdb$database + where NOT exists ( + select custom_db_object_flag + from ( + select rt.rdb$system_flag as custom_db_object_flag from rdb$triggers rt + UNION ALL + select rt.rdb$system_flag from rdb$relations rt + UNION ALL + select rt.rdb$system_flag from rdb$functions rt + UNION ALL + select rt.rdb$system_flag from rdb$procedures rt + UNION ALL + select rt.rdb$system_flag from rdb$exceptions rt + UNION ALL + select rt.rdb$system_flag from rdb$fields rt + UNION ALL + select rt.rdb$system_flag from rdb$collations rt + UNION ALL + select rt.rdb$system_flag from rdb$generators rt + UNION ALL + select rt.rdb$system_flag from rdb$roles rt + UNION ALL + select rt.rdb$system_flag from rdb$auth_mapping rt + UNION ALL + select 1 from sec$users s + where upper(s.sec$user_name) <> 'SYSDBA' + ) t + where coalesce(t.custom_db_object_flag,0) = 0 + ) + """ + + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + print(capsys.readouterr().out) + + db_main_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + else: + db_repl_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + + if RUN_SWEEP_AT_END: + # Following sweep was mandatory during 2021...2022. Problem was fixed: + # * for FB 4.x: 26-jan-2023, commit 2ed48a62c60c029cd8cb2b0c914f23e1cb56580a + # * for FB 5.x: 20-apr-2023, commit 5af209a952bd2ec3723d2c788f2defa6b740ff69 + # (log message: 'Avoid random generation of field IDs, respect the user-specified order instead'). + # Until this problem was solved, subsequent runs of this test caused to fail with: + # 'ERROR: Record format with length NN is not found for table TEST' + # + a.gfix(switches=['-sweep', a.db.dsn]) + + # Final point: metadata must become equal: + # + diff_meta = ''.join(unified_diff( \ + [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], + [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) + ) + # Must be EMPTY: + print(diff_meta) + +#-------------------------------------------- + +def get_repl_log(act_db_main: Action): + replication_log = act_db_main.home_dir / 'replication.log' + rlog_lines = [] + with open(replication_log, 'r') as f: + rlog_lines = f.readlines() + + return rlog_lines + +#-------------------------------------------- + +@pytest.mark.replication +@pytest.mark.version('>=4.0.5') +def test_1(act_db_main: Action, act_db_repl: Action, db_main_owner: User, capsys): + + # Map for storing mnemonas and details for every FAILED step: + run_errors_map = {} + + # Obtain full path + filename for DB_MAIN and DB_REPL aliases. + # NOTE: we must NOT use 'a.db.db_path' for ALIASED databases! + # It will return '.' rather than full path+filename. + # Use only con.info.name for that! + # + db_info = {} + for a in (act_db_main, act_db_repl): + with a.db.connect() as con: + db_info[a, 'db_full_path'] = con.info.name + + run_errors_map['init_reset'] = reset_replication(act_db_main, act_db_repl, db_info[act_db_main,'db_full_path'], db_info[act_db_repl,'db_full_path'], db_main_owner) + + # Result: owner of db_main_alias = db_main_owner, i.e. NOT 'SYSDBA' + + sql_init = f""" + set bail on; + recreate table test ( + id int generated by default as identity constraint test_pk primary key + ,f01 int + ); + + recreate table t_completed(id int primary key); + commit; + """ + act_db_main.isql(switches=['-q', '-user', db_main_owner.name, '-pass', db_main_owner.password], credentials = False, input = sql_init, combine_output = True) + run_errors_map['out_prep_ddl'] = act_db_main.clean_stdout + act_db_main.reset() + + if max(v.strip() for v in run_errors_map.values()): + # Some problem raised during init_sql execution + pass + else: + # Query to be used for check that all DB objects present in replica (after last DML statement completed on master DB): + ddl_ready_query = "select 1 from rdb$relations where rdb$relation_name = upper('t_completed')" + ###################################################### + ### WAIT UNTIL REPLICA GETS INITIAL DDL AND DATA ### + ###################################################### + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + run_errors_map['out_repl_ddl'] = capsys.readouterr().out + + + if max(v.strip() for v in run_errors_map.values()): + # Some problem raised with delivering DDL changes to replica + pass + else: + + sql_revoke_access = f""" + set wng off; + set list on; + revoke delete on test from {db_main_owner.name}; + commit; + select 1 as db_main_privilege_unexp_remains + from rdb$database + where exists ( + select 1 from rdb$user_privileges p + where p.rdb$relation_name = upper('test') and p.rdb$privilege = upper('D') + ); + commit; + """ + act_db_main.isql(switches=['-q', '-user', db_main_owner.name, '-pass', db_main_owner.password], credentials = False, input = sql_revoke_access, combine_output = True) + run_errors_map['db_main_privilege_unexp_remains'] = act_db_repl.stdout # must be EMPTY + act_db_main.reset() + + + if max(v.strip() for v in run_errors_map.values()): + # Some problem was in just executed statement + pass + else: + ############################################################ + ### WAIT UNTIL REPLICA APPLY 'REVOKE' PRIVILEGE COMMAND ### + ############################################################ + # ( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + chk_repl_sql = f"set list on;select 1 as db_repl_privilege_unexp_remains from rdb$database where exists(select 1 from rdb$user_privileges p where p.rdb$relation_name = upper('test') and p.rdb$privilege = upper('D'));" + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query = '', isql_check_script = chk_repl_sql, replica_expected_out = '' ) + # Must be EMPTY: + run_errors_map['db_repl_privilege_not_deleted'] = capsys.readouterr().out + + # This test changes OWNER of db_main to NON-sysdba. + # We have to revert this change regardless on test outcome. + run_errors_map['final_reset'] = reset_replication(act_db_main, act_db_repl, db_info[act_db_main,'db_full_path'], db_info[act_db_repl,'db_full_path']) + + # NO NEEDED because we have done reset just now: drop_db_objects(act_db_main, act_db_repl, capsys) + + if max(v.strip() for v in run_errors_map.values()): + print(f'Problem(s) detected, check run_errors_map:') + for k,v in run_errors_map.items(): + if v.strip(): + print(k,':') + print(v.strip()) + print('-' * 40) + + assert '' == capsys.readouterr().out From 605ded6cf0b7fcbb1235d992236a035c461e05d0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Dec 2024 13:36:43 +0300 Subject: [PATCH 0280/1064] Added/Updated tests\functional\replication\test_grantor_not_changes_in_replica_if_owner_not_sysdba.py: added notes --- ...antor_not_changes_in_replica_if_owner_not_sysdba.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py b/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py index 38d834b6..3ee9df89 100644 --- a/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py +++ b/tests/functional/replication/test_grantor_not_changes_in_replica_if_owner_not_sysdba.py @@ -15,12 +15,16 @@ select 1 from rdb$user_privileges p where p.rdb$relation_name = upper('test') and p.rdb$privilege = upper('D') ); Outcome of this query on REPLICA database must become empty for no more than MAX_TIME_FOR_WAIT_DATA_IN_REPLICA seconds. - Otherwise test is considered as failed. - - We have to restore owner = SYSDBA for db_main, so we call 'reset_replication' function second time at final point. + Otherwise test is considered as failed. NOTES: [15.12.2024] pzotov + Before fix, following messages did appear in replication log: + ERROR: unsuccessful metadata update + REVOKE failed + is not grantor of DELETE on TEST to . + + We have to restore owner = SYSDBA for db_main, so we call 'reset_replication' function second time at final point. Test execution time is about 7...8 seconds (for snapshots that have fix). Confirmed bug on 6.0.0.299, 5.0.1.1371, 4.0.5.3082 From ae66037bc4e1823cf20adc8726075e3726d1d1ca Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 19 Dec 2024 15:54:53 +0300 Subject: [PATCH 0281/1064] Added/Updated tests\bugs\gh_8353_test.py: Checked on 6.0.0.553-7ebb66b, 5.0.2.1580-7961de2, 4.0.6.3172-4119f625: every user is specified only once --- tests/bugs/gh_8353_test.py | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tests/bugs/gh_8353_test.py diff --git a/tests/bugs/gh_8353_test.py b/tests/bugs/gh_8353_test.py new file mode 100644 index 00000000..3efbd250 --- /dev/null +++ b/tests/bugs/gh_8353_test.py @@ -0,0 +1,66 @@ +#coding:utf-8 + +""" +ID: issue-8353 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8353 +TITLE: Report unique usernames for isc_info_user_names +DESCRIPTION: + Test uses DbInfoCode.USER_NAMES property to obtain AGGREGATED info for every connected user (instead of getting list). + This info looks like: + : + - where: + = name of connected user + = number of attachments created by , total for BOTH auth plugins: Srp + Legacy. + +NOTES: + [19.12.2024] pzotov + Confirmed ticket issue on 6.0.0.552: N_COUNT > 1 are shown for both SYSDBA and non-dba users when they make more than one attachment. + Checked on 6.0.0.553-7ebb66b, 5.0.2.1580-7961de2, 4.0.6.3172-4119f625: every user is specified only once, i.e. N_COUNT = 1 +""" + +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError, DbInfoCode + +db = db_factory() +act = python_act('db', substitutions = [('[ \t]+', ' ')]) + +N_CONNECTIONS = 3 +TMP_USER_NAME = 'TMP$8353' + +tmp_user_leg = user_factory('db', name = TMP_USER_NAME, password = '123', plugin = 'Legacy_UserManager') +tmp_user_srp = user_factory('db', name = TMP_USER_NAME, password = '456', plugin = 'Srp') + +# set width mon_user 16; +# set width auth_method 20; +# select mon$attachment_id, trim(mon$user) as mon_user, mon$auth_method as auth_method, count(*)over(partition by mon$user), count(*)over(partition by mon$user, mon$auth_method) from mon$attachments; + +#----------------------------------------------------------------------- + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action, tmp_user_leg: User, tmp_user_srp: User, capsys): + + try: + with act.db.connect() as con1, \ + act.db.connect() as con2: + conn_lst = [] + for i in range(N_CONNECTIONS): + for u in (tmp_user_leg, tmp_user_srp): + conn_lst.append( act.db.connect(user = u.name, password = u.password) ) + + for k,v in sorted(con1.info.get_info(DbInfoCode.USER_NAMES).items()): + print(k,':',v) + + for c in conn_lst: + c.close() + + except DatabaseError as e: + print(e.__str__()) + + act.expected_stdout = f""" + {act.db.user} : 1 + {TMP_USER_NAME} : 1 + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 872fd5ed13bf488a93e9aca09578b37823bb6b44 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Dec 2024 11:27:42 +0300 Subject: [PATCH 0282/1064] Added/Updated tests\bugs\gh_8057_test.py: Checked on 6.0.0.295-ef66a9b (22-mar-2024 13:48): all OK,every of checked system tables has non-zero statistics for its indices. --- tests/bugs/gh_8057_test.py | 470 +++++++++++++++++++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 tests/bugs/gh_8057_test.py diff --git a/tests/bugs/gh_8057_test.py b/tests/bugs/gh_8057_test.py new file mode 100644 index 00000000..c1a797e9 --- /dev/null +++ b/tests/bugs/gh_8057_test.py @@ -0,0 +1,470 @@ +#coding:utf-8 + +""" +ID: issue-8057 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8057 +TITLE: Let optimizer automatically update empty index statistics for relatively small system tables +DESCRIPTION: + Only tables from list are checked (with additional filtering only those which have indices). + For each index of selected RDB tables we get name of its first field (i.e. started part of index key). + Then we construct query with INNER JOIN that involves such index to be included in execution plan. + For example, for table RDB$DEPENDENCIES with two indices: + CREATE INDEX RDB$INDEX_27 ON RDB$DEPENDENCIES (RDB$DEPENDENT_NAME, RDB$DEPENDENT_TYPE); + CREATE INDEX RDB$INDEX_28 ON RDB$DEPENDENCIES (RDB$DEPENDED_ON_NAME, RDB$DEPENDED_ON_TYPE, RDB$FIELD_NAME); + - following queries will be generated: + ------------------------------------- + 1) Index for columns (RDB$DEPENDENT_NAME, RDB$DEPENDENT_TYPE) will be involved here: + select a.rdb$dependent_name, count(*) + from rdb$dependencies a + join rdb$dependencies b on a.rdb$dependent_name = b.rdb$dependent_name + where a.rdb$dependent_name = ? and a.rdb$dependent_name < b.rdb$dependent_name + group by 1 + + 2) Index for column (RDB$DEPENDED_ON_NAME, RDB$DEPENDED_ON_TYPE, RDB$FIELD_NAME) will be involved here: + select a.rdb$depended_on_name, count(*) + from rdb$dependencies a + join rdb$dependencies b on a.rdb$depended_on_name = b.rdb$depended_on_name + where a.rdb$depended_on_name = ? and a.rdb$depended_on_name < b.rdb$depended_on_name + group by 1 + ------------------------------------- + + When every such query is prepared, optimizer must automatically update appropriate index statistics. + KEY NOTE: this will be done only when system table is not empty and has no more than 100 data pages, + see FB (see in Optimizer.cpp: "... (relPages->rel_data_pages > 0) && (relPages->rel_data_pages < 100)"). + + Because of need to have some data in RDB tables, we must run DDL which force these tables to be fulfilled. + For this purpose test creates DB objects for each object type (mapping, sequences etc). + Also, "NBACKUP -B ..." is called times in order to fulfill table RDB$BACKUP_HISTORY table. + + Then, we get IndexRoot page number for each of selected RDB tables and start to parse this page content. + During this parsing (see func 'parse_index_root_page') we get values of th statistics for each of starting + parts of compound index (or for single segment for usual index). We accumulate this data in rel_sel_map{}. + Finally, we check that all indices has NON-zero statistics: rel_sel_map{} must have NO items with zero values. +NOTES: + [21.12.2024] pzotov + Currently only FB 6.x has this feature (since 22-mar-2024 11:46). + Commit: https://github.com/FirebirdSQL/firebird/commit/ef66a9b4d803d5129a10350c54f00bc637c09b48 + + ::: ACHTUNG ::: Index statistics must be searched in the Index Root page rather than in RDB$INDICES! + Internals of misc FB page types can be found here: + https://firebirdsql.org/file/documentation/html/en/firebirddocs/firebirdinternals/firebird-internals.html + + It is supposed that there are no expression-based indices for selected system tables (this case was not investigated). + + Confirmed ticket issue on 6.0.0.294-c353de4 (21-mar-2024 16:45): some of system tables remain with non-updated index statistics. + Checked on 6.0.0.295-ef66a9b (22-mar-2024 13:48): all OK,every of checked system tables has non-zero statistics for its indices. + Test executiuon time: ~8...10 seconds. + + Thanks to Vlad for explanations. +""" +import sys +import binascii +import struct +from typing import List +from pathlib import Path + +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError, DbInfoCode + +import locale +import time + +EXPECTED_MSG = 'Expected: every checked system table has non-zero index statistics.' + +IRT_PAGE_TYPE = 6 +CHECKED_SYS_TABLES = """ + ( + 'RDB$AUTH_MAPPING' + ,'RDB$BACKUP_HISTORY' + ,'RDB$CHARACTER_SETS' + ,'RDB$CHECK_CONSTRAINTS' + ,'RDB$COLLATIONS' + ,'RDB$DEPENDENCIES' + ,'RDB$EXCEPTIONS' + ,'RDB$FIELDS' + ,'RDB$FIELD_DIMENSIONS' + ,'RDB$FILTERS' + ,'RDB$FORMATS' + ,'RDB$FUNCTIONS' + ,'RDB$FUNCTION_ARGUMENTS' + ,'RDB$GENERATORS' + ,'RDB$INDEX_SEGMENTS' + ,'RDB$INDICES' + ,'RDB$PACKAGES' + ,'RDB$PROCEDURES' + ,'RDB$PROCEDURE_PARAMETERS' + ,'RDB$PUBLICATIONS' + ,'RDB$PUBLICATION_TABLES' + ,'RDB$REF_CONSTRAINTS' + ,'RDB$RELATIONS' + ,'RDB$RELATION_CONSTRAINTS' + ,'RDB$RELATION_FIELDS' + ,'RDB$ROLES' + ,'RDB$SECURITY_CLASSES' + ,'RDB$TRIGGERS' + ,'RDB$TYPES' + ,'RDB$USER_PRIVILEGES' + ,'RDB$VIEW_RELATIONS' + ) +""" + +NBACKUP_RUNS_CNT = 10 +INIT_DB_OBJECTS_CNT = 30 + +# SQL script which will cause filling of RDB tables with some data: +INIT_DB_OBJECTS_SQL = f""" + alter database enable publication; + set term ^; + execute block as + declare n_obj_cnt smallint = {INIT_DB_OBJECTS_CNT}; + declare i int; + declare v_sttm varchar(8190); + begin + i = 0; + while (i < n_obj_cnt) do + begin + v_sttm = 'recreate sequence g_' || i; + execute statement v_sttm; + v_sttm = 'create or alter mapping local_map_' || i || ' using any plugin from group musicians to role guitarist'; + execute statement v_sttm; + + begin + v_sttm = 'drop collation name_coll_' || i; + execute statement v_sttm; + when any do + begin + end + end + + begin + v_sttm = 'drop role r_manager_' || i; + execute statement v_sttm; + when any do + begin + end + end + + begin + v_sttm = 'drop table tbl_' || i; + execute statement v_sttm; + when any do + begin + end + end + + begin + v_sttm = 'drop domain dm_' || i; + execute statement v_sttm; + when any do + begin + end + end + + begin + v_sttm = 'drop filter jpg_' || i; + execute statement v_sttm; + when any do + begin + end + end + + -- examples\api\api9f.sql + -- declare filter desc_filter_01 -- ==> will be saved in indexed column rdb$filters.rdb$function_name + -- input_type 1 + -- output_type -4 + -- entry_point 'desc_filter' + -- module_name 'api9f' + -- ; + + v_sttm = 'declare filter jpg_' || i || ' input_type ' || i || ' output_type -4 entry_point ''desc_filter'' module_name ''api9f'''; + execute statement v_sttm; + + + v_sttm = 'create collation name_coll_' || i || ' for utf8 from unicode case insensitive'; + execute statement v_sttm; + + v_sttm = 'recreate exception exc_' || i || ' ''missing element with index @1'''; + execute statement v_sttm; + + v_sttm = 'create role r_manager_' || i; + execute statement v_sttm; + + v_sttm = 'create domain dm_' || i || ' as int not null check(value > 0)'; + execute statement v_sttm; + + v_sttm = 'recreate table tbl_' || i + || '( id int generated by default as identity constraint pk_tbl_'|| i || ' primary key' + || ', pid int' + || ', f_0 dm_' || i + || ', f_01 int' + || ', f_02 int[3,4]' + || ', constraint fktbl_' || i || ' foreign key(pid) references tbl_' || i || '(id)' + || ', constraint chk_tbl_' || i || ' check (f_01 > 0)' + || ')' + ; + execute statement v_sttm; + + v_sttm = 'recreate trigger trg_' || i || '_bi for tbl_' || i + || ' active before insert as' + || ' begin' + || ' end' + ; + execute statement v_sttm; + + execute statement 'alter database include table tbl_' || i || ' to publication'; + + + v_sttm = 'recreate view vew_' || i || ' as select 1 x from rdb$database'; + execute statement v_sttm; + + v_sttm = 'create or alter procedure sp_' || i || '(a_0 int, a_1 varchar(10)) as begin end'; + execute statement v_sttm; + + v_sttm = 'create or alter function fn_' || i || '(a_0 int, a_1 int) returns int as begin return a_0 + a_1; end'; + execute statement v_sttm; + + v_sttm = 'create or alter package pg_' || i || ' as begin function pg_fn() returns int; end'; + execute statement v_sttm; + + v_sttm = 'recreate package body pg_' || i || ' as begin function pg_fn() returns int as begin return 1; end end'; + execute statement v_sttm; + + i = i + 1; + end + end + ^ + ------------------------------------ + set term ;^ + commit; +""" + +db = db_factory(init = INIT_DB_OBJECTS_SQL) +act = python_act('db', substitutions = [('[ \t]+', ' ')]) +tmp_nbk_lst = temp_files( [ f'tmp_8057.{i}.nbk' for i in range(NBACKUP_RUNS_CNT) ] ) + +#----------------------------------------------------------------------- + +def parse_index_root_page(db_file, pg_size, rel_name, irt_page_number, rel_sel_map, verbose = False): + + # rel_sel_map -- byref + min_irtd_selec = sys.float_info.max + + with open( db_file, "rb") as db_handle: + db_handle.seek( irt_page_number * pg_size ) + page_content = db_handle.read( pg_size ) + page_as_hex=binascii.hexlify( page_content ) + if verbose: + print(f'{pg_size=}, page_as_hex:') + print(page_as_hex.decode("utf-8")) + + # https://firebirdsql.org/file/documentation/html/en/firebirddocs/firebirdinternals/firebird-internals.html#fbint-page-6 + # https://docs.python.org/3/library/struct.html#format-characters + + # Two bytes, UNsigned. Offset 0x10 on the page. The relation id. This is the value of RDB$RELATIONS.RDB$RELATION_ID. + irt_relation = struct.unpack_from('@H', page_content[0x10:0x12])[0] # (128,) --> 128 + + # Two bytes, UNsigned. Offset 0x12 on the page. The number of indices defined for this table. + irt_count = struct.unpack_from('@H', page_content[0x12:0x14])[0] + + if verbose: + print(f'{irt_relation=}, {rel_name.strip()=}, {irt_count=}') + + for i in range(irt_count): + # 4+4+2+1+1 = 12 + + irt_root_offset_i = i * 12 + int(0x14) + irt_tran_offset_i = i * 12 + int(0x18) + irt_desc_offset_i = i * 12 + int(0x1c) + irt_keys_offset_i = i * 12 + int(0x1e) + irt_flags_offset_i = i * 12 + int(0x1f) + + # Four bytes, SIGNED. Offset 0x00 in each descriptor array entry. + # This field is the page number where the root page for the individual index (page type 0x07) is located. + irt_root_i = struct.unpack_from('@i', page_content[irt_root_offset_i : irt_root_offset_i + 4])[0] + + # Four bytes, SIGNED. Offset 0x04 in each descriptor array entry. + # Normally this field will be zero but if an index is in the process of being created, the transaction id will be found here. + irt_tran_i = struct.unpack_from('@i', page_content[irt_tran_offset_i : irt_tran_offset_i + 4])[0] + + # Two bytes, UNsigned. Offset 0x08 in each descriptor array entry. This field holds the offset, from the start of the page, + # to the index field descriptors which are located at the bottom end (ie, highest addresses) of the page. + # To calculate the starting address, add the value in this field to the address of the start of the page. + irt_desc_i = struct.unpack_from('@H', page_content[irt_desc_offset_i : irt_desc_offset_i + 2])[0] + + # One byte, UNsigned. This defines the number of keys (columns) in this index. + irt_keys_i = struct.unpack_from('@B', page_content[ irt_keys_offset_i : irt_keys_offset_i + 1])[0] + + # One byte, UNsigned. The flags define various attributes for this index, these are encoded into various bits in the field, as follows: + # See src/jrd/btr.h + # Bit 0 : Index is unique (set) or not (unset). + # Bit 1 : Index is descending (set) or ascending (unset). + # Bit 2 : Index [creation?] is in progress (set) or not (unset). + # Bit 3 : Index is a foreign key index (set) or not (unset). + # Bit 4 : Index is a primary key index (set) or not (unset). + # Bit 5 : Index is expression based (set) or not (unset). + # Bit 6 : Index is conditional + irt_flags_i = struct.unpack_from('@B', page_content[ irt_flags_offset_i : irt_flags_offset_i + 1])[0] + + if verbose: + print(f' {i=} ::: {irt_root_i=}, {irt_tran_i=}, {irt_desc_i=}, {irt_keys_i=}, {irt_flags_i=}, bin(irt_flags_i)=','{0:08b}'.format(irt_flags_i)) + + for j in range(irt_keys_i): + # 2+2+4 = 8 + # Two bytes, UNsigned. Offset 0x00 in each field descriptor. This field defines the field number of the table that makes up 'this' field in the index. + # This number is equivalent to RDB$RELATION_FIELDS.RDB$FIELD_ID. + irtd_field = struct.unpack_from('@H', page_content[ j*8 + irt_desc_i : j*8 + irt_desc_i + 2])[0] + #print(f' column: {j} ::: {irtd_field=}') + + # Two bytes, UNsigned. Offset 0x02 in each field descriptor. This determines the data type of the appropriate field in the index. + irtd_itype = struct.unpack_from('@H', page_content[ j*8 + irt_desc_i + 2 : j*8 + irt_desc_i + 4])[0] + #print(f' {irtd_itype=}') + + # Four bytes, floating point format. Offset 0x04 in each field descriptor. This field holds the selectivity of this particular column in the index. + irtd_selec = struct.unpack_from('@f', page_content[ j*8 + irt_desc_i + 4 : j*8 + irt_desc_i + 8])[0] + min_irtd_selec = min(min_irtd_selec, irtd_selec) + #print(f' {irtd_selec=}') + + # Input, byRef: + rel_sel_map[rel_name.strip()] = min_irtd_selec + +#----------------------------------------------------------------------------- + +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, tmp_nbk_lst: List[Path], capsys): + + try: + for i,tmp_nbk_i in enumerate(tmp_nbk_lst): + act.expected_stderr = '' + tmp_nbk_i.unlink(missing_ok = True) + act.nbackup(switches=['-b', str(i), act.db.dsn, tmp_nbk_i], io_enc = locale.getpreferredencoding()) + assert act.clean_stderr == act.clean_expected_stderr + act.reset() + except DatabaseError as e: + print(e.__str__()) + + #----------------------------------------------------------- + sql_get_sys_tables_index_info = f""" + with recursive r + as ( + select + rr.rdb$relation_id as rel_id + ,rr.rdb$relation_name rel_name + ,ri.rdb$index_id-1 as idx_id + ,ri.rdb$index_name idx_name + ,ri.rdb$segment_count seg_cnt + ,rs.rdb$field_position fpos + ,rs.rdb$field_name fname + ,',' || cast( trim(rs.rdb$field_name) as varchar(8190) ) as idx_key + ,sign(octet_length(ri.rdb$expression_blr)) as idx_on_expr + from rdb$relations rr + join rdb$indices ri on rr.rdb$relation_name = ri.rdb$relation_name + join rdb$index_segments rs on ri.rdb$index_name = rs.rdb$index_name + where + ri.rdb$system_flag = 1 + and ri.rdb$relation_name in {CHECKED_SYS_TABLES} + and ri.rdb$index_inactive is distinct from 1 + and (rs.rdb$field_position = 0 or ri.rdb$expression_blr is not null) + + union all + + select + r.rel_id + ,r.rel_name + ,ri.rdb$index_id-1 + ,ri.rdb$index_name + ,r.seg_cnt + ,rs.rdb$field_position + ,rs.rdb$field_name fname + ,r.idx_key || ',' || trim(rs.rdb$field_name ) + ,r.idx_on_expr + from rdb$indices ri + join rdb$index_segments rs on ri.rdb$index_name = rs.rdb$index_name + join r on ri.rdb$relation_name = r.rel_name + and ri.rdb$index_name = r.idx_name + and (rs.rdb$field_position = r.fpos+1 or r.idx_on_expr = 1) + ) + --select * from r + + ,m as ( + select + rel_id + ,rel_name + ,idx_id + ,idx_name + ,iif(idx_on_expr = 1, '', substring(idx_key from 2)) as idx_key + from r + where fpos = seg_cnt-1 or idx_on_expr = 1 + ) + select m.rel_id, m.rel_name, m.idx_id, m.idx_name, m.idx_key, p.rdb$page_number as irt_page + from m + join rdb$pages p on m.rel_id = p.rdb$relation_id and p.rdb$page_type = {IRT_PAGE_TYPE} + order by rel_id, idx_id + """ + + with act.db.connect() as con: + cur = con.cursor() + cur.execute(sql_get_sys_tables_index_info) + rel_irt_map = {} + for r in cur: + rel_id, rel_name, idx_id, idx_name, idx_key, irt_page = r[:6] + idx_starting_fld = idx_key.split(",")[0] + + #print(f'{rel_id=}, {rel_name.strip()=}, {irt_page=}') + #print(f'{idx_id=}, {idx_name.strip()=}') + #print(f'{idx_key=}, starting field: {idx_starting_fld}') + + sql_to_make_recalc_idx_stat = f""" + select a.{idx_starting_fld}, count(*) + from {rel_name.strip()} a + join {rel_name.strip()} b on a.{idx_starting_fld} = b.{idx_starting_fld} + where a.{idx_starting_fld} = ? and a.{idx_starting_fld} < b.{idx_starting_fld} + group by 1 + """ + + #print(f'{sql_to_make_recalc_idx_stat=}') + ps = None + try: + # This must cause update index statistics of : + ps = cur.prepare(sql_to_make_recalc_idx_stat) + + # Print explained plan with padding eash line by dots in order to see indentations: + #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() + + rel_irt_map[ rel_id ] = (rel_name, irt_page) + + rel_sel_map = {} # K = rel_name, V = minimal selectivity (i.e. min irtd_selec for all indices) + + # NB: we have to re-connect in order to see updated indices statistics! + with act.db.connect() as con: + cur = con.cursor() + + for rel_id, (rel_name, irt_no) in rel_irt_map.items(): + parse_index_root_page(act.db.db_path, con.info.page_size, rel_name, irt_no, rel_sel_map, verbose = False) + + if min(rel_sel_map.values()) > 0: + print(EXPECTED_MSG) + else: + print('UNEXPECTED: AT LEAST ONE OF SYSTEM TABLES HAS ZERO INDEX STATISTICS') + for rel_name, min_idx_selectivity in rel_sel_map.items(): + print(f'{rel_name=}, {min_idx_selectivity=}') + + act.expected_stdout = f""" + {EXPECTED_MSG} + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From d9d02ef184030f00cee886acde5980cc567c989f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Dec 2024 13:45:17 +0300 Subject: [PATCH 0283/1064] Added/Updated tests\bugs\gh_8353_test.py: Added pytest.skip() directive if ServerMode is not Super because there is no way to get info about other users for NON-dba. --- tests/bugs/gh_8353_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/bugs/gh_8353_test.py b/tests/bugs/gh_8353_test.py index 3efbd250..4d8cbe7f 100644 --- a/tests/bugs/gh_8353_test.py +++ b/tests/bugs/gh_8353_test.py @@ -16,6 +16,10 @@ [19.12.2024] pzotov Confirmed ticket issue on 6.0.0.552: N_COUNT > 1 are shown for both SYSDBA and non-dba users when they make more than one attachment. Checked on 6.0.0.553-7ebb66b, 5.0.2.1580-7961de2, 4.0.6.3172-4119f625: every user is specified only once, i.e. N_COUNT = 1 + + [21.12.2024] pzotov + Added pytest.skip() directive if ServerMode is not Super because there is no way to get info about other users for NON-dba. + See letter from Vlad, 21.12.2024 13:07. """ import pytest @@ -40,6 +44,9 @@ @pytest.mark.version('>=4.0.6') def test_1(act: Action, tmp_user_leg: User, tmp_user_srp: User, capsys): + if act.vars['server-arch'] != 'SuperServer': + pytest.skip("Can not be checked on CS/SC.") + try: with act.db.connect() as con1, \ act.db.connect() as con2: From 0de0ff65f44c02c18123041ab5b48470d7565ab6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Dec 2024 18:16:54 +0300 Subject: [PATCH 0284/1064] Added/Updated tests\bugs\gh_6915_cs_cz_test.py: Checked on 6.0.0.553, 5.0.2.1580. FB 4.x not passed - see notes. Min_version was set to '5.0'. --- tests/bugs/gh_6915_cs_cz_test.py | 281 +++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 tests/bugs/gh_6915_cs_cz_test.py diff --git a/tests/bugs/gh_6915_cs_cz_test.py b/tests/bugs/gh_6915_cs_cz_test.py new file mode 100644 index 00000000..ce28474b --- /dev/null +++ b/tests/bugs/gh_6915_cs_cz_test.py @@ -0,0 +1,281 @@ +#coding:utf-8 + +""" +ID: issue-6915-cs-cz +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6915 +TITLE: Performance effect of applying 'DISABLE-COMPRESSIONS=1' in UNICODE collation for LOCALE=cs_CZ +DESCRIPTION: + Test verifies only PERFORMANCE issues referred to in the ticket #6915. Correctness of ORDER BY is not checked. + A pre-build database is used for check, see: files/gh_6915.zip (it was created in FB 4.x with date ~aug-2021). + SQL script that was used to fulfill test DB see in the end of this file. + We decompress .fbk, restore from it and check that for every testing queries number of indexed reads will not + exceed threshold, see 'MAX_IDX_READS_THRESHOLD' (con.info.get_table_access_stats() is used for that). + After improvement this threshold could be set to 1. + Only columns with attribute 'DISABLE-COMPRESSIONS=1' are checked. +NOTES: + [23.12.2024] pzotov + + It seems that commit in 4.x (2af9ded1a696a43f5b0bea39a88610287e3ab06c; 04-aug-2021 17:58) had no effect: + performance in 4.x remains poort for queries from this test up to recent snapshots (dec-2024). + + Commit in 5.x (cfc09f75a3dea099f54c09808e39fe778457f441; 04-aug-2021 20:25) really SOLVED problem: adding + attribute 'DISABLE-COMPRESSIONS=1' causes reducing indexed reads to 0 or 1 for all queries. + + There was commit in 5.x: 171cb7eebc365e301a7384eff96c0e3e069c95cc (date: 17-mar-2022 22:38) - which had + further improvement for 'DISABLE-COMPRESSIONS=0' (i.e. when compression is Enabled). Snapshots of FB 5.x + before that commit (i.e. up to 5.0.0.425) had poor performance for 'DISABLE-COMPRESSIONS=0', and after + this commit (since 5.0.0.426) performance became equal to 'DISABLE-COMPRESSIONS=1'. + Because of that, this test verifies performance of only ONE case: 'DISABLE-COMPRESSIONS=1', by comparing + of indexed reads for each query with threshold, see MAX_IDX_READS_THRESHOLD. + Before improvement related to 'DISABLE-COMPRESSIONS=1', indexed reads were huge for almost all check queries. + This is outcome for 5.0.0.126 (31.07.2021): + where f_ci_compr_disabled >= 'C' order by f_ci_compr_disabled rows 1 ==> idx reads: 352944 + where f_ci_compr_disabled >= 'Z' order by f_ci_compr_disabled rows 1 ==> idx reads: 1000000 + where f_ci_compr_disabled like 'C%' order by f_ci_compr_disabled rows 1 ==> idx reads: 352945 + where f_ci_compr_disabled like 'Z%' order by f_ci_compr_disabled rows 1 ==> idx reads: 1000000 + where f_ci_compr_disabled similar to 'C%' order by f_ci_compr_disabled rows 1 ==> idx reads: 352945 + where f_ci_compr_disabled similar to 'Z%' order by f_ci_compr_disabled rows 1 ==> idx reads: 1000000 + where f_ci_compr_disabled starting with 'C' order by f_ci_compr_disabled rows 1 ==> idx reads: 352945 + where f_ci_compr_disabled starting with 'Z' order by f_ci_compr_disabled rows 1 ==> idx reads: 1000000 + where f_cs_compr_disabled >= 'C' order by f_cs_compr_disabled rows 1 ==> idx reads: 1 + where f_cs_compr_disabled >= 'Z' order by f_cs_compr_disabled rows 1 ==> idx reads: 0 + where f_cs_compr_disabled like 'C%' order by f_cs_compr_disabled rows 1 ==> idx reads: 352945 + where f_cs_compr_disabled like 'Z%' order by f_cs_compr_disabled rows 1 ==> idx reads: 1000000 + where f_cs_compr_disabled similar to 'C%' order by f_cs_compr_disabled rows 1 ==> idx reads: 352945 + where f_cs_compr_disabled similar to 'Z%' order by f_cs_compr_disabled rows 1 ==> idx reads: 1000000 + where f_cs_compr_disabled starting with 'C' order by f_cs_compr_disabled rows 1 ==> idx reads: 352945 + where f_cs_compr_disabled starting with 'Z' order by f_cs_compr_disabled rows 1 ==> idx reads: 1000000 + + Confirmed poor performance on 5.0.0.126 (31.07.2021): all check queries have huge indexed reads, + regardless on 'DISABLE-COMPRESSIONS=1' attribute (i.e. it had no effect on performance), + execution time was 5...15 seconds for each query. + Checked on 5.0.0.129 (05.08.2021 04:25) -- all OK, indexed reads for all queries are 0 or 1. + Checked on 6.0.0.553, 5.0.2.1580. +""" + +from pathlib import Path +import zipfile +import locale +import pytest +from firebird.qa import * +from firebird.driver import connect + +db = db_factory(charset = 'utf8') +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +tmp_fbk = temp_file('gh_6915.tmp.fbk') +tmp_fdb = temp_file('gh_6915.tmp.fdb') + +MAX_IDX_READS_THRESHOLD = 1 +EXPECTED_MSG = f'Expected. All queries have indexed reads no more than {MAX_IDX_READS_THRESHOLD=}' + +test_sql = """ + with + d as ( + select '0' as disabled_compression from rdb$database + -- union all + -- select '1' as disabled_compression from rdb$database + ) + , + c as ( + select 'ci' as case_attribute from rdb$database union all + select 'cs' from rdb$database + ) + ,o as ( + select '>=' as search_op from rdb$database union all + select 'starting with' from rdb$database union all + select 'like' from rdb$database union all + select 'similar to' from rdb$database + ) + ,e as ( + select 'C' as letter from rdb$database union all + select 'Z' from rdb$database + ) + ,f as ( + select + d.*, c.*, o.*, e.* + ,'select 1 from test where f_' || c.case_attribute || '_compr_' || iif(d.disabled_compression = '0', 'disabled', 'enabled') + || ' ' || trim(o.search_op) || ' ' + || '''' + || e.letter + || trim( iif( upper(trim(o.search_op)) in ('>=', upper('starting with')), '', '%') ) + || '''' + || ' order by f_' || c.case_attribute || '_compr_' || iif(d.disabled_compression = '0', 'disabled', 'enabled') + || ' rows 1' + as query_txt + from d + cross join c + cross join o + cross join e + ) + select + --case_attribute + --,search_op + --,letter + max(iif(disabled_compression = 0, query_txt, null)) as q_compr_disabled + --max(iif(disabled_compression = 1, query_txt, null)) as q_compr_enabled + from f + group by + case_attribute + ,search_op + ,letter + ; +""" + +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_6915.zip', at = 'gh_6915.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + act.gbak(switches = ['-rep', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) + assert '' == act.stdout + act.reset() + reads_map = {} + with connect(str(tmp_fdb), user = act.db.user, password = act.db.password, charset = 'utf8') as con: + cur = con.cursor() + cur2 = con.cursor() + + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = upper('test')") + src_relation_id = cur.fetchone()[0] + + cur.execute(test_sql) + for r in cur: + idx_reads = -1 + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads = - (x_table.indexed if x_table.indexed else 0) + + cur2.execute(r[0]) + cur2.fetchall() + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads += (x_table.indexed if x_table.indexed else 0) + + reads_map[ r[0] ] = idx_reads + + + if max(reads_map.values()) <= MAX_IDX_READS_THRESHOLD: + print(EXPECTED_MSG) + else: + print(f'UNEXPECTED: at least one query has values of indexed reads greater than {MAX_IDX_READS_THRESHOLD=}') + for check_qry, idx_reads in reads_map.items(): + if idx_reads > MAX_IDX_READS_THRESHOLD: + print(f'{check_qry=}, {idx_reads=}') + + act.expected_stdout = f""" + {EXPECTED_MSG} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + +# End of test. + +################################ +# SQL with initial DDL and data: +################################ +# create database 'localhost:r:\temp\tmp4test.fdb' default character set utf8; +# +# create collation u_ci_compr_disabled +# for utf8 +# from unicode +# case insensitive +# 'LOCALE=cs_CZ;DISABLE-COMPRESSIONS=1' +# ; +# +# create collation u_cs_compr_disabled +# for utf8 +# from unicode +# case sensitive +# 'LOCALE=cs_CZ;DISABLE-COMPRESSIONS=1' +# ; +# +# create collation u_ci_compr_enabled +# for utf8 +# from unicode +# case insensitive +# 'LOCALE=cs_CZ;DISABLE-COMPRESSIONS=0' +# ; +# +# create collation u_cs_compr_enabled +# for utf8 +# from unicode +# case sensitive +# 'LOCALE=cs_CZ;DISABLE-COMPRESSIONS=0' +# ; +# +# create table test ( +# f_cs_compr_disabled varchar(10) collate u_cs_compr_disabled +# ,f_ci_compr_disabled varchar(10) collate u_ci_compr_disabled +# ,f_cs_compr_enabled varchar(10) collate u_cs_compr_enabled +# ,f_ci_compr_enabled varchar(10) collate u_ci_compr_enabled +# ); +# +# set term ^; +# create or alter procedure getstr(aorderid bigint) returns (aresult char(10)) +# as +# declare base36chars char(36); +# declare mresult varchar(10); +# declare id bigint; +# declare i int; +# begin +# base36chars = upper('0123456789abcdefghijklmnopqrstuvwxyz'); +# mresult = ''; +# aresult = mresult; +# id = aorderid; +# while (id > 0) do +# begin +# i = mod(id, 36); +# id = id / 36; +# mresult = mresult || substring(base36chars from i + 1 for 1); +# end +# aresult = left(mresult || '0000000', 7); +# suspend; +# end +# ^ +# +# -- Generate test string data +# -- 000000, 100000...900000...A00000...Z00000, +# -- 010000, 110000...910000...A10000...Z10000, +# -- ... +# +# execute block +# as +# declare rowscount int = 100000; +# --declare rowscount int = 1000; +# declare i int = 0; +# declare c int = 0; +# declare str varchar(10); +# begin +# while (c < rowscount) do +# begin +# select aresult from getstr(:i) into :str; +# -- skip y, z +# if ( left(str, 1) not in ( upper('y'), upper('z') ) ) then +# begin +# insert into test( +# f_cs_compr_disabled +# ,f_ci_compr_disabled +# ,f_cs_compr_enabled +# ,f_ci_compr_enabled +# ) values ( +# :str +# ,:str +# ,:str +# ,:str +# ); +# c = c + 1; +# end +# i = i + 1; +# end +# end +# ^ +# set term ;^ +# commit; +# +# create index test_cs_compr_disabled on test (f_cs_compr_disabled); +# create index test_ci_compr_disabled on test (f_ci_compr_disabled); +# create index test_cs_compr_enabled on test (f_cs_compr_enabled); +# create index test_ci_compr_enabled on test (f_ci_compr_enabled); +# commit; From 925aecc6314a691064a7819508acec67a41f3cdb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 00:04:51 +0300 Subject: [PATCH 0285/1064] Added/Updated tests\bugs\gh_6915_cs_cz_test.py: adjusted names of .zip and extracted .fbk --- tests/bugs/gh_6915_cs_cz_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_6915_cs_cz_test.py b/tests/bugs/gh_6915_cs_cz_test.py index ce28474b..bd802642 100644 --- a/tests/bugs/gh_6915_cs_cz_test.py +++ b/tests/bugs/gh_6915_cs_cz_test.py @@ -6,7 +6,7 @@ TITLE: Performance effect of applying 'DISABLE-COMPRESSIONS=1' in UNICODE collation for LOCALE=cs_CZ DESCRIPTION: Test verifies only PERFORMANCE issues referred to in the ticket #6915. Correctness of ORDER BY is not checked. - A pre-build database is used for check, see: files/gh_6915.zip (it was created in FB 4.x with date ~aug-2021). + A pre-build database is used for check, see: files/gh_6915_cs_cz.zip (it was created in FB 4.x with date ~aug-2021). SQL script that was used to fulfill test DB see in the end of this file. We decompress .fbk, restore from it and check that for every testing queries number of indexed reads will not exceed threshold, see 'MAX_IDX_READS_THRESHOLD' (con.info.get_table_access_stats() is used for that). @@ -125,7 +125,7 @@ @pytest.mark.version('>=5.0.0') def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): - zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_6915.zip', at = 'gh_6915.fbk') + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_6915_cs_cz.zip', at = 'gh_6915_cs_cz.fbk') tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) act.gbak(switches = ['-rep', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) From 9c2a5e3755d7b58b37db2df217aa12d8cf4fce88 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 00:05:23 +0300 Subject: [PATCH 0286/1064] Added .zip that is needed to gh_6915_cs_cz_test.py --- files/gh_6915_cs_cz.zip | Bin 0 -> 4334750 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_6915_cs_cz.zip diff --git a/files/gh_6915_cs_cz.zip b/files/gh_6915_cs_cz.zip new file mode 100644 index 0000000000000000000000000000000000000000..2c4eb30cccf8c926aee087c1a8ac1e4bd9b02c44 GIT binary patch literal 4334750 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≪>7wON>(4U{7KR-i%erDpD zLr3mkqJ6%Te&O}vN28WM{?ma2uWgMg|8iu}C3^3Yo!ytzggjSW@x@0sOXqgEeqlYm zVGq5bh~99N-k@b~m^7pMhyVOE;5+{^72$Z=t$lM3rH~4&GK0#}rPJ1jUwo3v!I~LU z6JoN-Mxg90d((D$QxSVp7JC!<0$lWEZz3U5OdNaDNeYn-!`Yvx2UND49{L|X>zliH zF4et7-H1!@*XF%c=u4lqkHH1zwy^5udDZ>@M#G`~3OWrOnG^8qiOSILQr8wwnBqoM zXQ}E6)fZ@Io;ZGt=u>Q4FpJ1tHN3Ak4I-QH3P@!jMWf1^}O;19*X(x>A8-xxS!>HwO zf`H>_dwz&fcWFH_*#CSu>N!;%LOXs8K-=?`aH(i2S}H0*OGONdv)uDlBaMusrw){d z{wO))2rgg3@us=gffxaXdmV_;gVa{{T+Q|Lx%Vi-d$nKIE9Q-(7vrArx?|?c{m*&! zUN>~9g>>CcyjwnhKvCl5sj8wGNi|#I8sm=!TCH_7+yWmiphJ{7dfA+RO~qJcV;K8} zj(tJ*XzlgRwfBpd`UDEJH>`XfLaF5DC!*K9WeRcf&^#iNY>?B#~GU@sUKLL4-Gw zi28II2~2mJ26sp~kJVc>jU;ONnyKJ(A@NQ%#oEbT%By?HD%xT&QS|o_{Kvg^U&&kA z2j1-*TN3O^dn+}kJ+QQFJk$@S?i5Je^9nRHt zn$_e)7AX7Od}zXZuO0KeWY@A~J>2)cL-fR&>YEnAW(UJN*4Tp$NMhVW)o%Qf_8lua zbl2W43q-8-qqHc~TbVf2YO7Z#dZ@PC>Q#m9p=y3B63O7;?=nGKzq+?i(5Qt+he z5nQS+V!_U(>Y^lI>xV)K@u@VlgS--svIS?9PRCL!?!@(e2NT09E26Hx{EO1#?$r{` zWu)R9OBkL6hsDB~mG46X8mSh?3ZeqEAY%4TacRkh0G@}N71kUE}XxJvZ)VPy5VOiCp6fBZl-c`XalREgF(}PO@fKES2SeGFy){8@^(Nq(5{}@lT3) zK?wWh#Tlz-^y~8PqPW!)*IXSlUC~TBm?If7T&XVVp~jW!qT4oCs*BcscuIB3{#fIN zxKds8LE}nw(Fcty)f*kmEzByoQeAY<=Sp?aRK%6)qN#{0)x}cLpGB$e$Rn3UKDPbB z6sycOGX&jfrn*+YMGfcQQ;Eh#jJ0Z-5%ANb@&Urv!JR!XuRC8QtBz{3LfF-9^nkB6 z^61F~^)U*f$D!|_ry# zR)^IpfoM9*Xt)~7s_;{DJ?&L@!A(%ae_Z9;u1C&K00swm+Vm(iTyrH_xN~i~D7wM5 z>0(EBu1yyWB9drW(WXm?C2T~?M2uB{HHVRuN?7&nSgS!~GC25gO6BgjrxM*0AN){C z9s%D{M6&_kQuvnAYAYzdrHBO)-%>;~k@YP_!n))zT3w=nt4l(y)g`LUxp||7gwJ}l z{ru;Px997Z$hsvxcWU}QY2&J^>_mCgf7>u)0*5Q zp|{rKg|~kMKoRLev0RegvU=*0aEn}=)i<}QwGwxSwuN+PU3WeLSWJy-eFU)PTH085 zQYI+kzdRJSpt$JAEjjW#y8B5O?4!`?!2r0)XRlbR2dR*g%oAodTE>h-3nC?45WzL` zBhZ3~*=e;Jv~gr6jfM*%xS{FP0LE&&EJh0=jnyCuV0C~HCMd#n724FUk9*&_Q;{!9 zm3NwWF#v5stUMpBSp_#{7_NK950*(H{nf)(k8wkjZ@uZ^@BQqsaoex=&D*2@TlY54 z_TCciQ8Dl4nHjC6(6$OPtFTIwYz~CkVm!x~uSU&!5pdBhsz}+;s*)ab= zd(cAgP7r8~mwdFdvJ%e0aSmE4DuGKyR@o9#qT|caQc)mWD*6H~73HC&qG-5O1lRN_ zL`y|#xT=Uq1XxqVV&PH|QH-$YD3{Puk;ZB&l5fpeHAi?q-mmTVkDYPzs*dvf!{OlQ z&?82ujEF0m~DR+@*Ac;{A@O1&i`Z-tQHCM3N4=6jDUSXkw8?AMn!czL`nA(;hk1DKC? z=G%x?MP$Nlkv|;rRtHH4>r%VQe8fr>n$3aSs!viqAMx`;;RoVIaB*YfOsJZI*3;nP zMloHQ5>8SCcQPe_4vV<85p7T5;zllR)U_7J{?mvXGlsSk6m%{)ccJphh@Jj@HoH$= zFP3KM2-oTbvicb+xY6=tuZKl!;HM@rvK>D)i9MYfs{npggF)^GYd7k8ujuTvYh^-* z*d1Fg^vx|voZoe3+}`8$MvQl0CY`>DiO4o8IV=R==@6{Fdd@ zzIa~2z`Jw&1&?7bwv%Po#%CUSC+mrhiszl=jL;Z7u4UMd6_z9<`85Qx6X8OiUQyo& z6Zw0LRTNvAww8(Z&Kyjw#F~pjy{U#?)Xy_ycx{L{t2a=6YEp`)kRu4WLrQBV4j3=H zcbprsP|Xok3rN*zFIb00t)5I;dmgm!Lse&`9YaL{j0LGh zpk;7wh#(q7+z>%56aDE75js|CXLCb@#$#u=A%gb}5rPjlL^#1rIc=Px;hgrGG(>pI z!;cvvjQJvAX5>)qf%sGBv#P7J(s@>tcIK+`wb6p^Zn(J=+@!1cg(bkc{t6-NgNai*nH|mJg+pJ9(Xhn=tL$d+ z$H8guQ0+$psOO`lA|+fZ8jhBVx}l{a^>{SY?kZX;%7jZr`_NL+TWF~$8ZH%4;|8mp zI0P;g!Bs`&XsM_QE)^X>OGQi3QjrEO6@7+w&%U+#oIN_I_@Y;^?89Z7H@@PVG*&;y z@9xbXZ#nj8!Rc*#B=JF@6kZ2aDj^l(ba_@3;u3S~0syeNkmMg~lt<>)vfEd^HoS~X zT;|3xd7AY05h0btXsu@es%Q%=HC&$K5bo9oKq16ZH8RCjQK#6-QdM1}G4BK#D&jxc zzjVTHMK8Ski_+un)lS0$#U<)TUtb?yOV6fc!$qjyU_OO`IGk9e=t`^kUwmnu_Kqa9 zB7${;M0$ZvTMVl$NI4vb&8n$V9WmL%P4Jkp?}LlSvr|UIt2#a#?Ao=W3|vb|y{_Gz z1a~J%D1gOH-iB76=A-4O0=OW8JLJ$qhs7t)Lkprzv>;N$Wg@rV_6XtY8tDChA%iIqNlI>2(*N1qgd2q=o)f!nweLDQ=0O9L#ojotFdo%N+uWlB3b#j}0_vis%O&*i7)W{mP zMAnU%BPC>qdmv8ib~K@k$N0jDpH}PqCmJ*bPz2S^+iiX(Qv8gb+lAe2$zcB zs-lxEjjs6lc3u#>6(KcRX3Og2 z`_YUGN@CY?zMNUJIx#?+dqFH%^Owfa|D+3QtJj=fQNuh#BzelLUXZ_@u4P{l!wli> zA1ln^p1))UK)W(IHhtSniMn(FGo*tHDrOxI6;yljuIT?j=!s}^c-4*fVQSkYp@B?up65SIY{7@kwpF9Ar-#G;h=y(YYoJvD0 zot1DwGz~3?C>3CJgc;r0P$if(@+8be(QrWoH{5hAS`ZyZ3nC3%5QSRHM5@ghL)!^n z?t<6(;!C%pE=%r!z8wugOM)Y;ST(PfvS|i4VroBH5EY;Wks6NmM6)fhJeYT*1yLqk z5W!_4xCv87(SoSTY7oihlO3#_Fa2AEzur$I5<8%tp7RBm;8^|squ7@ zK36qo@P$g6;L^xy)aAljIyp5^Uf0auUrxQO`guI&e=W_DC6-1OQElGfGNri=vwO4Y z!nva<0M}t=!+Lms#*!ej%QX9ICxx;|j8r8b@|Lr+FqX`He@0AP)xwkixxg+gsH?d? zUrNb)9AaeEMn%*t1qdcH!GCmNUIld?u>woIH@URt3u%1`EY?J|5OKFTj=0;LwYu9Z zzLqxjFA2>3xcB9+-A^wnzZB>5m#-r3>aU=OLaMn`NpNt?VYKtky=V}cG7U{*{u&zW znP#<`Z(1bpG-|o=(Uw!4j%9ao0qq1<0GEo$_v!y*@7e>RD%1DjB9cu;W;K>6wWU_B zftew?g1;=SR4h&L4m&EgVMg9CFQ64!Ynp2rngLv1XmU1p{1fSxKxymmWpD~o>}aG z{H}`{p6Im~6Nj|*Sfg#R;NDM9mWAyxfAwIqMI)d6cZ+Qk%AJghB_je(#|fGX54&9b zW@YyDnS`!h2*LpHBVVflG7~G1dM~CEh(KlUAb-6Ao%wj21+GXhCFz%S3RR zkgL#wC=xD+;4+bAq@_>T+*XoAq{Jt76_5LNaA!0P0~es> z0zb57LIhlLvIqm4E+*>kd)vj^bHN+WKbhfD^;FDH86$gq8opre+&7)f;XHq->!Ml; zWIj`2K`^;7k{nB|uT5|%;V8~@{;6ZwksM2%htqBnCWc@s2a|dR1DC2IW_B-LVu&&v z10lK2A+;^Mz#4@ZSm_o6E8@tAcz4OoMRJ?4{hiYX(&PKhH?-^t08jXf`|zsIpJ+;yc<9_gT-gdMhl`8v>-CVWg+l=D!r+(@5bMAc4{!VmXhNEs~p&d*0aP8NTXy^}|#}qSo#gg%X3nDnVVmRjJ zDYPIm!37bWz_D;>Jc}udL8S4|KNb@zc`n#6V93DUD<&R^x^Jl_ap_^*?O7KuhM-3Q;}2UWcDpX$LsLcnxNW~JS(bKb4PR(#8u3SsJ1x1htv6=K)umG;~^UeSrpc=AdOLJ)BJ0 zWQ)V~?6>UOGMQ6}bkqIspO+iaVm2jyDt}1#O?U@Z&KE2I1Dj)Eh zE=zqkqw!-#pgpuKI1GtS3Jtp~hW=q`|CK!5U-ZfvS(H5Ip;PAPAM!jh;^i%UgT5i5 zX9h<*OJI}D2bWMBUdO3Dc09HH$)1Kh=ki(gWI)zj~H;NEJc;mmx`3PEi9FBEwfmOc9CMk%s|_)SE8LjQ{awQ7S9f4({ehxWCThXfl;UTRLAvd(QAgcQ@aO4 zE!85p-E1={C5-Enh0bv+7pqfG=Per>L3JhsY-v4;me4k6d8wRfJ{W0vsoKX~eNOW6l6(%0 zD%}$G)DqVv_b-fg0yC<13-*O0-i}5q2VX!dY7)_QY&~2M!O?$cU&iuVScw)y5pY37 z143Bn2KB12f+!U&h)i%nWRd-2NJt)Zi{vgz9>ZKUPnM-u_i_4+QZU@93yy-b8I7Mv z=R7PXhFnIP7MueoQVGz;WE)yv`iF3>h@(saaY^(qj8G+H)vrU zYcZ_LE+)>rPYU&JK`N;|=V+>ac&Bglu*Dr#gam!!Y<41@q3X@YvvKr>aFogzOIxZq z8$e)LLqlvB0i2=nFQG{DMckP8+I`^yq zC%Gxy(z!A`!Y!SrR%C#)@Dgt6+*AaoxhdSzxv5CFrE^n}We=|grz!P5zys}WgPTmZ zsF&V24yss@UkAuPgVvSq3^$n$Hz$#ghK}dLX*TbG>#LND&Kql< z`6bQ#PJge@-g#AB2QRuQjgzIj+hn{LbS@oLuRpP#SMp8Fx{nWe64K0ch} zGTXoWw>fktKrA&VCFw+25NuQmz_jwmGD9WaVEnMK%k#pE+eR^Cw(9XJiOyQbm(Ho8 z9l>h&&B`@tT&7j%u**~Oz(r><@ zW#2&hZfEfjEstC%hFkEPusS$bv2|$326c?EW*T!X&h0oeh~O9i6!=*17&VBnf+z(o zh>UQVXgyjGok0ttGPoeJn2B_UM#Q^IZjzMQx$yF=+|tL#I~_`(QWQ(cBMgl*#fAl; z99Y;q9+ucGoB=DG_tG4+Ao4AMqicM1)XM$hO5!Fy^(s|+&O|aSIvhFOi-z8KJZKZs;iyr0)EjWL zP06zYcFbIy&fv``75uB1B)*kW5c%_R)UqBsWf`win*G}}tZ1Nu%ED5WT}TXal|qP* zbg87OqRpe4TQ@}0LOH7zyh+rkomoM^ktE=R8{x2x*U-+NsTRSO-gRopA*7c4C!v-+ z=7vhlAk>n1JA+V5z9D8BoGT4NEtwZYE76b*p_Y8($VRQAeO)Ca)RK7<3OAKna*T`Q zG4e#YcEh6bdtPcCSrF*{S(nU8XK7B3LhC5xZM4McqNp# zFxob!w@BuWoR;%g%jiI_W?vlJp6OA|-odJU%D#-IZ3mLd8@}zm{qw(H$o$$8rnD%0s`|cZ z8$!NxKSoMQSvA-qt0ZbV;A}@EspFh#GN!El?bF~2hU=2M==K2if2fI9LI1aqa2r8W9$Pe1k5(wOWjv9 zje1*uRv~F+ZO>!(LW&+0R3;UY48`{N8y2^*<*2)b28&v=6QC^=!}ZV>s%GpMZK0T8 zJ=#L~Qjl7BacfA-l82=2@OobQKUaU96y0Ldjj&q-2t~OM=v~L+R+3{PmI+ZJS{0p3 zfrZ7Tf+G&Xv0yCDXc~`>$a9xm8Iw`p_Q&Yks^5A2YSt%fT}RReuiP8o0LZ%j1A|4T zg_CZk=FieR7FIrJ3-|iLMLV1x9aYv?LDUN^h)i%nLH&So^}!ykD{u)YyeQ_j+@pu-`WpzSv?r+N zR~Ad@UDjVyOOwC`aZ}|r35**M6+4BvsntRhmc>n}@^U7V-?-6YRLz-|)6pd(P|665 zI=!blu2+j*GrV1?)^Hk-Am)B}q%Se|!(|Q%G>R8Q0*&GZkwBw(K_t*9ZV*|l)SU?i zMOnmt-pVfT;OZqw+DY$?eYVKUrR<)sKQirX|DbmR>`1*2M0DMJ(UnQG4}otCpIZlbky0-mTNT_-#%8kkW~sQl^mSls_p={uDbtoe?)jdy zx$VI2U#;pg*U7*O8DLsKG@Ju*)JWXgg+*2RDTE1v}w(S~?h z1F_TKxPuk?w5gR0KrUbAaGaf$#I}Oy!KD-cibNRMby@(?4gJFA-s!86B+X|Zt@8eM zUFqMd1ADzvS=iiVuoFk0_n^Trxp2L=)fUUa1}AFuK3EJ_N5HAmPDO(|N5hp`G{}e5 zQr?M{ic;WG5gcl_3N00x;8GFX*!3K^R0JpVn2wf;%HUGbV6^RH+2k=XrlwEx#8Kd! z_Z@o00E@zk7C}%->?+8t>flC6E~C9@!Ej`YFVT)4!_fA8J)FUWhtxYZHkeTt`UX72Ug#U}wk4r&z@=JPoSHJM&&(bu#jNh+x#s(K zew|@HrfnPh%;E8OCJrtyvl4KQjXPMXoArZfCQ&^vIF{k6qqc{wxM~f{HdP6_Z7w8- zlu9?ijtk^c31+g@t(~Tr$u+jm2mhU0jbQsMBo26k#X{nMcj^{`n_TZjA#uPBBDf&{ zIOJChp>u=CVzKT}R8S_pD>K;A5ISik&TS=W+$GKT-=F@vi+OpwX6<@E;_sL9(^vF&IlO;TZuDR77ffUest&Tn zTN}*9>!x=vHk4#vLtTR$ri+q8#?>~LL*x*yv(6Pbk8-6YMBl;XStgF}M@n{88tfKab+pu44I7K3OWQ#z8oNa?6^;4fFcd;8N~Gym#BgyDv2l**QtwfzwTIfr09NScDh znwVl9(#!-K1`nQrc1~GoG1O~IVke}D6tr`S$>KCn*|Z!z(@k|J-PFf30?lW=?@0J~ z?Y<7VKdg7M{gNO7T8&n*&WzQBGshx_O@L}PYYEh$S`3rb`>!a~%|2hYhm>8fbaV)U zM~5nhfSpN2VUE+wErJ9)8?|3re}}7!Bz?8~+di)Ew|V1S#p6F6+c*8OEzz55u|D;8 zD&zk#=?2slcqKnnsE;8MbpDUViVBz{6vdzh7 zE!9C$k+#?f(V<3J>!YoZ01qWC+XO%BfpiX*on^vRczEWNF)`a&We0Uyrn9z zyj07w{U0Vyf}{<8@9}2;XkXsE&%jkZ^^z0Y2}~LV3wISGYP_LW)(GYB1=Xblh!M3L z-9s9zzaVhlgappbg22hiGlIa$3v0^+PUHII-nU2|u9C+WmlmAf9QE`P*CqEajIJdM zszXVv_g8!^&Qs8l*J*^w(P&8H3vlQ#Rhf;O{nUHB>O4q2To8>#3nF?dShRwbXh9SK z7esJ9k07)lN<|AI6I>8cyP%QA*;_3uz8To*{WYB)-7~&h_UdWf9}GJe(DK7hA%Fkd z^i8?N=8_9J6O4O0Jpo(3wi9RT%52Dxy?24`Qftfyd_vO#doYAyA-~Yb>{pOzj>14!R z7k4hB&)2{FSzb0>95;OFygeHpteP?6nexIf=pRj|3s%qtJL!TVy5RKif9~zE=!8d` zoP$J*NbNx-(^Kyf4f7l+_@8M@KW4?#V`64aCBSh?OPVNl!bPXr8xflzI!H{BnF>I) z8fuz6BOsd~#7nY<(QSCI*4p*+h`jV=YFoQfgA$APBAi@#fMPD%?k${Lxyp`w+@6M> z9&w45q>PN`E0^>gB3)?j{^YEpf4LGdO$Bq7x?wbdeDapt$bXh9Grs<_MIfI7`LuJm z$uja;mlqneNRIN#y$G5_Kjhab3# zp5{Y!ckL9owhkO!u^n1rW1`H3MKPu1fYpOfg*$c)X|!AEB$?hkv;#yLTq?3GsjqH= zu6I_8L3?Jgqw~8ig2Fd+Bhg;8WVnY0cMe^{J!Pp3P%TH>^Yw6&&ePHM{BStD2M*2H zgO-YN;ZhNtG|XbOR1^W1il(BaqS5?R^sImWX^%kd!UYK{Uux6-Y4gEa1=XYL2y?7O zZBzm@glMYO3yvw83hA8AIzmdozILOm%891hfwCGci>4AC_jiP|>;k#5NFn6L(yFv- zRGUXNw{D0gDsw~I7R9Dhgz7r=UYnjO6RPXHfE23hydgl#s_XTzpx$xQpO?HP$tS5* zz(*OsT)lmPGaMP~9gc+J&E^GqMFbwvkvRuup1$BfSJ zcUTef&JhC{r`pDh%*sAjp-;`fW}_7(lUljCOXdl7h*AOrCVPj)Xi}KFR7;qGs@6l&PI~3} zZ_3N>dC3{4hiB0Mpe(ffAB=|o==mFx%7cw?IO}FKnszbYKs|C=PDhuFKq(_|;ORdX z{4(X@i$Ch!?ofFsA(l^{P&c-8l-{uz_v_FYlR0P^GZ!w1;B3%{REwo7l#LcdDQH2& z3Qep`v>q*p&Y%TR8C($YGm)0n0g{iD;WM+M`l{xxm}Wx*^SRiYBX?yTTs;Rjb_Zt{ zy9X^73_?3to-KfV0Zt~=X!TjV!2O{ulxpP1mLRc4~?Nz6A9YKGSc$52d1 z+qTQ#2IojFyb(EeJKkP<<`|a2kvN$)H`I%!BdK&Kl#u~ueZ zrx0V)_J?jzg^IW-c~-!VnTyjIpD@ZgWSe>Gsli0dpC`w%j36eS0;#%8MAj!@gRs1% znp4+yTv}26foMCDTPzEGtd75EJ7#fE9MN{PYb|hvpNhE87-!m@_bm><0RzipG z;)0`(sVjH_cP`B&bi9(%_pdMm>N+%ZV*uJQ&=(G_C-X`yPe2hq+~{$VT%3%TYia= ze&khk*TIV0%!XX5zacJF5#mzmb{t45SL!{g7e9${2P^bxQ!Ckyykx*CU1`(-m;@~UrrueI0aMKQPK9zCo+vze3%RRmgO=n%|S8Nstk zhakcV4r&9Q_Vrk=V-VvTzJ*u|cwnbm%x0^#5J;`;RQsEm*}VP^R~Je8YWcT){_#Xs z!jBb?|8#8M^vAYDtBftex$RWK)e#%eDA)U_hA$&&8eXZd-W8w2Rim5G9@;E!CBbJ$ zIrNIoe7IBHqrHx#gRlsMo6wG?!Ek)N&(Vf{cc7&rJzOf9iqf z`kmIz+V%8u*{CibQH=ca+D2mJpEr+JHWAHKy%Mcj_vM$Ozw;4?K2=asd_nj#Q6?1r zOkCoY@Mq$&|CloxT667CDDa@5m^Cf;%z`I+c_1IuXiQ+Uqxl2WEmnu>>tz9be%fVYJf)1R)kUVxgwf)JShCJpr zA7F8UoieI(?8v4EkR4+q?`xzLFnVwQ{1u*ok`$8gu)pVjCRM-VGoiBZUC;jN>Iw>Z zES`*`74ldXM-LoI9IH1qF$JxGI|mNNTRFYWH&~-OIcTbHL(%9qQ_;e@Gg?^d;erUx zr~!`L(v}}Y0d)!o!$V6;rkocY1<_HkX3ju#6nHqE=qPa8Qgj9e(-YvgVAY+GU>3kw zZ7I=F;I*a7;DSg_N8#Oy>g}SVAUX=7qfig`uu&=FrtB!R>`5Jk7}il3`m}HCCUf@> zJrBK4Erpyn%C9tzJKAN9W-Jch+x|fE2U}Uo!aSZ3S2pimi>a$)09O0gZfq4?uD0A5 z$%PaIrG;}2CcTRZ5jBEI`#~<%Cd8#;l2(nZqFrxTy%*}n5a-G;OwXC1t^ZCo{EF0R zIqO|AB`G6m#qLqLX~TapKi((iudcl_Y|NcD=3ig9p(im4&OIx`4LylbaBgo(jDm9& zX5mti7zO90A~6ci9WD~1;9O)=jDmBi$#C5=F$&)19EZ0cM!~sN5gb0gm)`_d_kd=C ztBT;v8#HLo%$Lvp7%(ko(`^|(Ud{Ua^Ygua>D4C}I#C$4fEG}eL#_1+be6>__CrsX{1lHns|1immT;E}73uj}-4 z?tHa*$aCQIHLKBx5kh{RhZ_j_dG3jiFF$X(kQn3|Jzt8R|K*9Vi_YeKw>Cr9{6TMZ z>r-DiBZ1Lqbmk)uh0 z&p^usE76W|DR9Y&&z0^SH$B|VTjSnm@Ss<2_c;`Gf33j5)r-g2X!i9)!G@$H$_b9V zL~UQA#t3!wfEMS&cb0Aw624=ubL_m(7|L#@&lMSB+g{P^3C7^ejE4ODr22d>ripUnq+ zum+0sXk~=(+vZ}O8_}lHwxb1+@Z07Ek?`B*v&i7i4^%#xsrEEe)vcy#WTU&bk)Mgm zF4p!G&h4IAwPIH5$bvxk&(yttv8C|BMaO@TD#xAJQh2X98-T;g25_Jq9jD4wRM%}Z zPuAsYGUx!4T!0HAxJ*R!6s#cHixxy>{2=nUf5vOBzFyDt@!ECY!LdsVE@cPYHeYl2 z+ef!9YWL0D%BERgmIr|AfpBs!F_K$69=5{Vn4OJ}HC$GL2=Hc_W3ABHRD)GoAM@UY zxKzO)OJz8Hd`>{G#S>E4+kPd8@K=(tLQ&y8^ZWe#X2gfcsy)2aaDL<`p#@Z7aVOYS zy(ASR;OpmxnTUjH6O~(dlGAKxhS!ei7eXQWIE^F8ER+T~a!!UX(9Re+XjBC~+_`Wv8sDV=E*0^q zW;QY*`LC4aE8ay*MSgIpXd_xG%0^2?5pb#KRkT!e3M~~G;i@7!HDN))k#MPq6ymUu z*E49Th#lXs_(X6HC6#cg2(Bu68g2Vn#DCB3jJx_8@sj%zFL`53&=cLOcFyk`J*@At zfl2FM7{|Dss)D}=#MV0CzB>C{Rqm=Ddl{E>Qve@HX-s)l0Z=ceDv=~+F^R1OwB6*^ ziQd-7?o@>@>ydE%D1G7KzSLO9YYC-Tu~cLI^Os4IRtkyTIL6QXc}$B;*GCgn9&kq6 zkaTc`ANe3+RW)#fmvA~)uc6ftsr>U*P}tm7lEz)qT**nx&pRm84w&zPP&?oax(c-e zZa)JKZJ}~bs2w!fhZ1TBT>VXhH8&y!M9mdK6A(3T9LOjjYThBh3W!=|Sn0m}u8UOMuIgr58YQm@ zCK`7`6HGMjh9;P3+zm}I(Rdr04sJseOf)WtB$#NtVr&Yi zATlPR1rZ$SvIs4RBH@AvE)#7<%S2XKdh`j4JJ~^!0=-&q+|=E>d<%&*}T zenOPOUm2yaMh~1xiqu%OF${z;#%fXun>caUC5cswi392Q@3rd(B$f1JYSzmAYMbuv zL@}c*sPIhW+}*3`%%s6#;UMQvHy)aaRm>O@DySl-cQ1W+=gF4lCG1r?nM_r;L*FC2 z7A~n|_Ey@Sac-z)akl3%G6P&_^=2Y4Y@841O)M;Z88I~!Q$?fj{vkK+gDa}YFAOiW zGw~&5c38P96kEGEIrE~d$f7g-^N&V{N>WJf3xDohaAx*-=a33?!?UU@2u-#I4PT;F&%^lhI8FW{wu7>_nB#A3{T2ExXvgM(XavJ>z9?Ixom+ly*M=)} zB)Nv=UQ~gWiu~YG5u7~yAhc8z0hfy4>;Xrkr6MC-RaAY#Ol6&>|P?yWS0=i z>QF~SE7!yFqht4C{1Wl?o8I$eDf!hGQ7=IO6%rfY=#z*!p|mhOkE$#ccM>aJt9FQq zsuyCSisUCM!@Jq#4@p{2Nqb?->>tuU={MidQf((i9h@QuDeYr%-Ik-3&B16#9UYt< zXBt`%Ek+9>KeQk+!eyd8XhF0JEr=rFf(R}XrE`NwcW6YsyObeGnFER{?&&&Id-q@$ zf+5uOf}|!nRs#mNs zv|nOgyoq6+QG^T8vv&5f8K{V1f}S~5R-EotyQDYW5ME%>umxUV(R{*oq68;a9BUL` zj5xvy2sanWZNm0_uZ9#r0(a0=013Px5oxJm;VVk%=Ef8vp!Uj~Wbd+GN?$}L1E9xS6!>=m(iAusWQqD-%NF*Xb%=0oUyu#I1K#Tpa>XqE4YDr%3+6J3jl( zoi1J;YrH$HADU@67)TPTcO-ngc3+3c^)Kuk6LY+MVb`qcNuPw4^xLCJ4mdF(w(4+~ z%z`B|+DwevcEG1%tz$1qIXNL%(LZ3*FIhh(=9s$cV8w0bhV9X;Rs4ZiaU=CEiP&}^ zsocRqQST4f6n(T*oA8!uJK|C$Umxp+6US5ApX_N!XK#AI^{;&Uxaoh(2-LXu@p)v_ z?cbkk|NZKif48{uGeb!U7db&3-dEX-x#H5bHO6Px3z(iT6CTRi{)G&6&trHp)fyF} z=mSQ%q-p%d<#ugWn7rY4>RC<5_!QUQSS4fY&SQLH@+L2&3E=JN?B>`9%({YYRW(SG zrGIzB_uF&{+rH@*8h(`%7b*gAp&C^%b>c#q5EqIevNuLJ3$LUSvLrZBOer9$H*;!{ zv{FcH%3O0yOp8p{M-y13q#l^D&vaMVZJy!>SuZdbl7Oixxx_(N|fm zsp3A*YU0LUq?Kqv6ag1RaGNe2k+6a&6)lKNa6!a(ZS}p7sCzKFj}$$B`AEN1srntC z36+KKsy)sirtF)_maIa+o3bB8Q|mAr3R@y8IJ-^PT8`c!4RrR#A|Z_6RwkwkiNo7U z^SxUv7;#`$aPNOq#J}g>$A8oQk1y=YRbQTP^;iPk$31 zICc$}&119U0ZtPimDryY7S#CWCThXfm2TJsXpDSMXwp&t~7wx#1X*ZsdxxleVT<Ipv>;+TAXJsbHW?MicqyUssPX)wM&%%)PAAq$`4n0Zu{{MVh^Qfr z1^iNX94m+_`9btnw*SMD7d04zZ}Ix+M{{}eJ_A?v)Jrr3sHV!IpzHINThR5nV?u(i z&kG_!*XITiT%TId^+~X<$@w~6Y<|~8ShJ{bRQQeDQ6}U1wD7XwgbC=wYPVg>T;qwn!vaLuT%XVZbapF1&~txtL$J0g+dt{LYn|fHPIq0rkmcq z*ie#fnn`%;g&;=&yRyMM#;ap}^#&02>F=DkY$?|XNjL-VwX_~ZOK2;!yi~uVq{g*u z8amoVih1Q^Y4M~DKAjU>2_RAvLxijPDD<&Tfr)%#S(E!KtuSW?mU%@k|5)nizFyOq zR1Jw*d36CstGDj27~vSMeD{d5x`x7RYA9?L4Fwj%qM^XWf<;4tr?Dv-3fv$P4Fz5h ziG~6!j!wlekkw4n1ftLdyoRXrZo$lZE3OfH{2lut}bhfwVla#020voMh$2u~;x3 z9kI2$lo{CCeZr^jw~ZZVzU!G53x_?M=}~a;0!=BE(p!JSWV4bC-6l{~MxqRkJ6NGl zn_9{4seG9Y*?jfM1oa>?f5enD&7pkA##eXy}DgWvR0=b$_J@Er{5jf)zw?nTTJi*F9c` zcbP4A(W?1D)F*82QAs07nzi5m`Qv_1MR}*aQGWRjN##O-)&=YJ6Fzdhi6-GA$DLIY zgXz2=(&dW5be^}bI3)4Tq~ego746_3l1SZPY=q>#pp)msKi{+9<2gl9e`@7^G4avi zYdY#kwn;?UP$bfr6o!&phvjhJ{_87hc>pis^S&k5>u3 zTS@&GK2)1im1ql^Yb!I}Kwb4hQcJO#=3VpPEyJXa`xZ8O#$PHMfp1%H(?IhkyrnW7 z9ue;@Wk^!y_k|UuPYl)GJ=kTlx*#GAbYO|x5qgewm>Gt~wGqnrJOL0qWqiI3#2n_s zR?|`ViaH9<_6;c&+?p0BzU)bn! z1z2uE8{O;8m*$s!`%XoBVZL+&0%sr$gNL-xCBLgmssc(`hu^6UNBFswjrKj%5l*oMP`ByyOxR`d&<>vo=&NwB& zGg`47+M+Ii4sHrd%%*d9Nimzw!xzPDI(ch0Ed?cJ)49dJm`&%VA~BoJOGRQfotuip zY&tg;iP>~+DiX8lyi_D+)45%Q4hQ(N>FNTjv2acRiD(3nb8wUKd=q)?#l#`5QlJz) ze`DE0S8jjj(_SM~3?r(mh(2YuTov?Ncg7nHs3Ndi4h&y4ljZdJ<-8!D`GsI z7uI4t-2vn2V&Vo(ehDrU@in}d#zC#s+Jt}qdNnUdSgoC6GYP-Xo^#||8!E3JJD%G9 zWKTmLnNqC{xc-|QjOkGVkSnw~Js@9Utp-0Uv=ln12<{4 zc1a=eG>J+=)YV(yCIq^898j?reAP*b9RQ8&?HY@Mau`_Xs;g= zv{Erd_?r`(Im6P;2}28_(P%*w0T)DYmgG~=f@ls}5cy_JZ}W|cQ{7EZ*|2@l7mmTn zcY!n=trb4&TUhZ_cOiU6)s+xF<5ht|_>6aMzDb48ayZ#tK$#IKn7=KzOZA!gILc&C_6=T@U|X2n!QVRc@_Y`U0D z|J7byLxY%2=cOVso6et2KPhI@Ij^EY%%<~RG(CSd-Qj02IutiSGoFC9=O@Auwa1_} zGgt8ShnKeO`R`Ee!ZqHVj-Kk|^Y=TqmIi$Au-m2yLlXm+#PqIe9Jg{Xgi`y5j3fYw zr$U-)BkXhouhGG4X1%Vaie^!!jfg1gUTT2;&M$TFbEu8ohTv|~f5;GQYpkdATv7b4 z!MEk`8ZRx!Yq*+74Z&upyi_S?t1?JGwjq#yY>-R!0^(BXZRvF=-bNY)xl~p})yio( z9bL$ajo67pd{fL-x3+mybF1p)L^vdPDq8v68I2Oe-a{;MA_;wAkrQX51yNhHAc}ws zA~@-GIyHcS_h><6f(s(5^RY5fCLLWWsR(KU>AOZwbaRp1o}9ij=|K9re)A12`v%gH zs0ozGI^`GZze5M-RkI6ijA}U_By#jqX__e#OhbAqhDg&l!%$WoUmH+mFqSm-ux9ZV zqXiKgiiHXyBU~mT)*4n2twIZ;NVp(^%S5Dn$_XOfp%GiVOPPVK-6wqd^~x#c(|ubk z9QJIcN5RDl>JyV?D+|=ab~h!@3fM7oaryx=&5CmDRKLBdsrmD0{8Kh%mjh!7)l{n+ zIJOd#t^Na4VU%(nSHnwgW@7R(NzzIov0u+MkBw=O>H27by!qs&4<~$Tt)_ z&j44^z%}6EBQu1Q$jsToYYaEh{u9p!q6V2m{jLxOfjj> z8&1WWR4)*d>P?`$HHCoaw(`PSbX&Q(k>72lj>39(iIk7rbT0o`AJyUepLX4OYm&O) zv=*&d<%@<<>5ifG@wXgEs^+8oDqaCs2Ea|ejO7-$hV{v3CQEP6@8r4vk-77Ky)v$4 zE0>Wy$d2hRW6GPRUCKsL>S2JE=g94a@2;slQV2Q{55k1+>?e2+3%fioytr*t4f%Dv zqfk#HX$jlRd96iWbE*<;!RZ>0uq}x45Jt+Vb}!X+dcTf&U#We>Rnl0JUEVFwn~=qn zR%!h+yf4J%MSVDY>G?t9qaCS@$j2THaEkTWXoXD#4H95&+i(Jtr_e^AjAPMIGMYum zcZl1R^_-)o3&}`0av5K;zUg1&aPG?)v{b}qny^w4oWf)!Tq+uemWtp6d)v(elQ#)wwp`aQhCqsj<)CP;Zo5Uv{Y1pmWqsnxqH6v zkrBn+rLT#Nc=n^+W!my7&EJzYw;kC1t5sd*T88!-$7bw?Eev#A!V^1SLtS{Y^7g}q zc0aC$z%ipd;4PISfXs8%!EpyG^l4Ko$HeRkC|?#@WdBq@a}KBlO6@}bf=fx|+fhh) z5P#Cz(2r4&BsWQOXG(Ei*5J_Kz-HUj6-a#+E%|4`6*^>kXV4IG(cl&xoJc7hU^tU0Dj#u3=^YD-W-|*|GjecD4LAb# z8MGiOLkl7u%?~ev3Txq)&Yk%`hZfes{IH(qpTCTp6Qq!YFS_KOE`RDur=N4@d-iWq z6oJuY9SR2zK&yIv>5zvd<0FhJdF*~jm0UgdFf>3wjQ?;c?r^+cI2r-m_>YOd zooW0FPPvC@-(TSU{ONyADb4%)SMx`-rjA03bxVkYU=?n9{P>)Jt#h-sD0ek=V+!`@)=;<8`bgYcS2q6 zIwVG!u<$4`%EWc0gDYun&QYd8w@B`iWsk*f+J~-685Ko|xd;L!-EK z4u|6@O^<<$LpyY7NX^w`ukn>b0jWi3Sb{Gc`EE2?Sd%V4mLzZ@S`g{sf(UNXhO!7& z5UoTDq6mHvRWkPk$%ot%rc_klb=zGr&4vc%bGs*wnoVMpJUX~4faq*k!#8k}?r=)3 zgV1upDYX7#BtJRDXTQ1KMeD(=*{0on{)Z^vrLJo}KAhw-+g}JATqA$R(jr=m6j^~{ z8ZL#OSyC8hEGB8!!|@tBG#N+^n>&gwk5|4s-fnifLj(@21~IKz@0v@5z=74WuGR@0 z?CwUK1QIxSsm=Hi-+%O<()K^SOgc$zywwF0BH)y&;mmV-@hK*bEbRDfN9MhWrE$3x zZrkR!1Di&W9Q_s=;24U`YBNgRMWBtO35h~xW{Guxh(armHE7SwcUR5?Ef$T827a*k zt-(=e_)fT*W0UHTqed;ZFPIdwbLDO1@2e(9Nkpo8ZQrivUAv4 zL$Ovxy?U$2kgDC;i~PxNYf&u6X$$zGX=@s`C;wVKA5PY+!>Z_nlj zt7Z(R3-<26axnBr_ivM4Ye`4ygR8q_ruLvi=Tq+zhwdE7fShSdk7NZU-C0wqt2M<5 z7gfiS(w}Uatl|NeEEk&Y$i|#%teE~a*E~!mD<;DRv@<&#HU=l#I0NmlwGwXoMk|v| zG9l=ou((!|C()J@|8@HVhvrnhmC)h4xZvnx6L=G5_TquV(PHZq+@s`|hW0)LdDyi< zus3;cg(gg}H#y_bg1yO|1QqN}-b}qv+tW{!XUF^>@K!UYKfjt0*gWIpzr z!+Yw{!;?P=E$O#MlN@kjLTuIHE|~>OX0(|Ywe5gU#o943$J-Zn&8nVc_a(FUXf`SO z2W+{`h;0Xw${qM4ZMlbr3myi!RNE1kY9``R`JS8*ti*eyE4)U1&10`=ybbSbufnd0 zvR>uh{sk*NC2e%5HnX}?Kkb(d1K)D_iKKe0Y!O^$3SU+;C+orUi{v7pbnbN^%h)o) ztAhlK31d9LrVADS`BW5I-D1k65(nyrSR@+AA_mVAjqKjHGxsB?-WvlQW!(_f7avI> zS`u1Y*QQND{UOWM zhS-dwA4$u&GUJ|)E>$)6Z8fJP&~1a_=5CREEhv@gdT_{DZ!{`{39f{P)1$0JV|(b} z1_}0&cV$`A^9tUFl(9~KpNn(D08DJdEs#+Z(6gadKB2+b%F@r z&NV+P1QFzo1=D-kgjS$>ehQ7)!e!vI)@8b*xMU|i}ZXrI8K?+YdDcn#lk> zjl{&jn~b8dCMOsgkY$XNvapZ@I6f=cx5*iAYOur({~!`Bh~P3&C~4YZg|!|nH-3&5*0E?| zts`w1IYBg!H5kdnF(l!OF1e@6pSsfN=iK?8{S|AR)i&^i)+$#fQ)sOUtyR0h8#;f; z(OR{qCtmw%H~k$e;UFov=_sPEU|FLEp#@PYS`eAwf@qw)Akx$kjne0u|0ak=)+IB0 zTPpm&B8WyjjWOZ8!Yh+x6OG=DTOnzle$lJ%#!Z(Ct8ex7^ZEOleI0^VUopw$hSCdi zjozD_{Oi2V#s1X{)vV%UtxQEEBvJa_bM`Hz*Mum4d_Rub)y=cL3@>XA>f#$=|4$FEt{@p+{fFm3(70DDy zqbgEiT2%#FD)NI%MR5JQL1?Kc0xlK7b$v#or6MC-RaAwe^N|1(Y~7amO~qsfpM5OO*$g8;_1KbeFyk^m0G@(K*Sj zYWRY_(Zd#ZSP?QVe(e7)u1F_0H3reSoXC3cCmR+1Ux#2Bmozc^TvhIw9@p5e`+OR~ z^w=D;>M9k96@*9^HNhAC!{CZ}eI-|hD<1x;`OI$S|BLNfUGlX1XNtQm3AwAL>xREIiwJ8oa@9VGU=qCOq4DLF6Yhh~gQPp!Jlr z8#X1)uGo25C>+Q;^DEcufaAI)qQPct4h{gN`)-Y=nt8k>{F+qcoTS5B)kJ=XLVODu3yG(SP_F|Z_cgcat)+8=^6J2He~F%Y zwRlT43Ua9+qv|`t?{eGI+1T0yZ+I?j?!7)5Nz&}uxaXbIvmZ8_TaEA3;YYX8iqjRd zWMUxJ@oVi+Th_sy3;&LW=?CMHInai(a^Ub6nR2Rjyg^nrl_sN6%?jXBk<5c3pB!%Q z74M>@B0soP1lK#uMoUEzaH$B6e}4)s6&c~GA|n2P83VwjA~?y-Gia%ZVRLds=9RCC z;0XAYaH$BcDta2Nl3gV4Ju~zTOFJQH++Oth=#@)T_g3w^;}P$XZEm|SY5iIPWSeRO zI0iAxavF?T-L!MoY-eIljX7sUkR%EoJV(=Kct|Ge7vn7zW|vBCRFz#w9O4=sDn-v< zzGL2?OL@<~_@mxU1>-g2p6PAAvD;0;k;Ean6Jd`0+ZOxx1~QGrs%nU-k2U8AR~pYi zt082n(Hjqsh@1Y5Hxm%`61DU34~ z6Sw(r{PiAI&c_vZ$2VZo30%?Ycg18At|++>uK00T`&*_39t!aM+b^fyYZk1yXp#wT zy6ESe30kb7xnMLPZwOrF2Ulpp)iop0f{3`~SgLoda)Ih`u%;tcCW31z3`YwhX2%E> zM64E&6GQ=VSD%x7yd?2B1>s1;iZZw^~8^Fb=#@f2H1 zEa%MWyJ`G>+moeo;FL1yteAC}zAnH3FVAqxw5f9s>42ri@qal}y+SjT}rrz+f=%#ls zHk4$WX40hag`nT?Zzhrtz?nS#T|MNQWNqZpOP6H(cW~9ZOWH{ro29<~<2cVD-{j3x z@8pPNI>3a^X_ZUbIxy5-k-)z@;KMe0(KZDl)=34E}(Yic;WGQ5sq*YKNAJ zOmL|PuIHKxmx|!3qCB)zR0fxdNWvFu2p|USnK4aPIndF2+5S6SygV0pcN)FsKewD~ z`Ad-7EpFSB_CL0Ec>W-TsK1qQ2P-Db{pJ@s&|iaBC&~pe>p`IGYvf9K5+GnvN;s*A z&d}F5oPx`0HJ4R?aJNRs7&QR+`0tNZx7GQbgobLsi=C(G(fCWkW(H+7T}(%6rj{W)rp(HwTPQ|2j@BPwoN1X9;w^?|5%eyv@zc0IjZHY)x? zkjOjMC}FJ3+Dq|HpAJsNZ97^4zXL6Za?ygw2q&78j21*&(1IuhE{NbV(N44=+KU!M zWio@PPuSd60+YpJ}K1ObHN+WKN|PfejbXo5U1HdKsp}%esr7Xrw6*t2I3rAC)nT4~R6xjD zs?=#Y9bGa4rHsHAPbZyBUn`^%39?mKA<9Zv5lx^>2M3x7sYG6=%C&V@93K->iQG8@ zA(hBGUm4*t(H}r6G0$D&MpB8LrtkFHUHW{P+rG0y;#<1CuDH~Zo_fYu3gK`b8f|65 zLds|Hp=guE=h2|N6u6!zTqEc;G*W2edDb~PzFSu0nGFmDsMoUFyaH$9mY@LUe zicD~+Xf;~*?i;lCEcOF5J0M@UD0&8ML+gyTq3Pf@w0yJ|Ef;P>+kuuGXUN;o$aayK z1R8fq^Zm=YX;mj@wT>(ZbpK3oEt$T1yKrG z5E=naCq<`fDd7N$TUZZp*nAzSWzzn!CHZzW2=G@pl%SCCim+ zHt10!u4!$Aw;9pHIrgu`o0I}tsgDa}ofkBywwdICl*}a@7W+<5BUm=@sh`r7^ z^P=cKj(w-?x*?Wdl1eIA8gp2ZvHOO6%yci?^Yn<%Z$0As7l)WXXR-kaxS(QPI;f^=tlC5$5c^!gKVOp`EZkwuSOClXTiHg*?u8<- zgm!@w>GVN>!;2{kx6p78WMMl1C1{^`UX*=Qr$|+VSoXAK*-+S*~Jx zBaD;KN;Ci>MIP+WUPNUV)FcxT399WwO#2}%KkvZW3|;dFy%m4t1~@+3RJ2g;+mAu!3Cxwl2Y1rc2Le9DGlfCcT@OG4WG8wiXduG|dr1dY5i_|XGB9JxcC|4>kB|NNRp3;A$ zad|j8)SY4rR(~2d;&gTiVcA%sf5shgh3r^YO4X$D&&A3mGtBLIvXo$+-?a%Xuc)=t zzK)roH_X^kOkGq9PgdRgsP}8WD-6%0BRb5Zs|lmACy(zX$ZjgD7GNYUD@mSJuXyIM zGQ#WLHs6!ScL!9ap8vU!QsUuwpfyWJjI8RN$#Vl5WL77>f9ziTUPIh%P9W|!sWNw) z-gOEGBPNHI{!)DY#UJ%*|2FPVcGy zpjV4tGrV2N9I1u^A_JSCN>R=~8GwdX`I4z_4VO{*=8tttWq@<2dQ~1;W!=xTXSu`C zf=CY+MD!4<>{()mW1wMZLBzbrv6?S%K?J8tIt49==AZ?UNoEkemF>Tyk5(f0rS(JI znseGoIiGu{Q=VvSmKhu7RdGRLJ_J~rr6=m%+WHeVQWOJ&J+E%^khVTN51mt7|*2-x) zkGM$QQbxwGUacHE`-b@}<^;T%+ep(euyk zo>{d*XeGcj6@*p-PY^g)CLdR^-cM~0idjZtbvURt#{#E?RsydI5LyY`j;_#3;0BS* zOym)F^*Kq>NIqG{y-^Q8{Z6RMU5AuUmvGWoaffdyNqdCxGF&moyje!e; zR|nHLaSaJKVrKW^C59+NO<)B$|2fWKQbE6kk5z%yG4ARs89tKaQ}9KX+_af1D$UP* zxH>lacI8bMeBsy}v(WaW&TuDXya92vZ97O3_ek|5|mj;G3W#fR+TxzuRLg|L3?JtGIb#CjGI0{^6{hw!V!;!E|s_b=h8nP z@7HXb;;f=vw1ta++f-yeN#)OxI|;PJ8Y+|7EvxPKQ+K^mnFBFp9IOd|WO--*$Z0v7 zZp-lTYS!nUpSL^T{Akp`rLJo}KAhw-+rL~5MyG)~d9`SLR+Zj=MX7G~`LaC(Nnh#c zRLKf9Y;wH@L{d>005(n=`ZXBZISm8LawbgA>iVU^5M>z-xl}hq6~t}2j`l;87+uP z(1OShEr^V8bRRgC;v%#lii8UyxJ#qsuJSUgxA^Qg zce;3atRaDeZEoj|Mvdw3KI!bFFK;QCc2N~tDYdNSAsA}R_D2w_77rIAfS3*JUq?V5 z7It}FcyZe(#zC$gAM2!BHc(H!mW*6?4>?td&eeEk`Ze|Cu&u?&6pSzfGdQ9Ih9ghG z?uAL@%UY`5{`t!!Nh^iK?wD&{9MdAx_0a_7n_9wxiAO($tNMfm6R!;Y<5)0lV-`&N zg$0wtrQvMMtipnc=T>GA7EG}mZO^uFnr+ zm+a-Af7&BZyKq6m%9mQUf7(3vfjbgv1P+d_BUD*=N2>z4kcKLhNkX9T(4Uo%OLd*V zK^>-e9rCHh<08uD4f?*c+0+Rf{2s%GOW|jh6vi2gooA>;C7)#!eRq64z*yB~Gs#8K z%Pu4a{VB$UiipSFIqQ0KcJY}guRnbic6+yIwy`Qp3LJqp#hZn;ZR;p|VKL?pz}0>v z_KdY{??z)Pb%!gD;flX8XsM_GEfpCDqopDPS}O8`OGR*gf?d#3Q3PBn8ikgMPQj%j zxT@$ov{V!cmx|ydHks`OmY@J!DkA?IEEUp9v{a;nBgpI{bpknjP3^^`srPx#@6=+! z*Qdiv#{2I2Wr^o4ZrhXgKeo1?v3HdkyeU(?v1S0uSPcp_780ZT%|XcNu-tEwqt_6* zGP$S|N7U3Y_*tGs3}8pgw;7d0O1r{WHlW*W8c)-aRJsuNz#O+Lg5 zCp}G?t-gU4tSZWDIYq|O=2$Cki$iuLO*_1$VlMJ{OGQ&?cuSQlcd5vTt)ojupp+3f zlU$tBgo`ufs9%+HueQD?EnJ)@@Thm;XlFv<;>=}Dg`pi%*%S;Eun+;KE(vFNC|sPm z{7sob^cJZexoT-*Y0}1uM?X86{^6R8u-hN>wvkvbW0!*ihed+o#g<4=++9v2C|(fx z694cUsC`$i+N|=qaVT03e=1t>))}pM)58tl$eiG+oR;%g%jiI_W?v%J_o+UAY6_rePK5@mtySS<{2*PT;p%lsj;G4}=}`nqI2k3CpSh)qgm- zgWYq@^Mu@i;(YQc=9JzyTxg>Y+t&lsg9u2Ybt+p|{h+>)7*%5LF z+@1?7IH8X1OralZqD06Y@HX9EXh9_84!Dq}?Q#b@dM6CKG_L=PKkD7?_|QfbN$bZO zjd1y3rmz~i%&`)M>jKHN8d7%hmc28>(4f}>c?T!s;SulpNv?go+@~&Y?$U9-Ip96_ zKK|?Xe|+KKiH&OLUL1!{R#-U$F%9TLZZU~8^(irTAnxT4BxuYVj|amB(= zNeb~^*Ufd;3&m-%0bW7(Mpg8Ys5e%v>~T3!rcSitm5q+1ak1nDR><1}l$Vyug)9EH zpveoApq;%U;D)kvXtmZ#v{Ymqjh2c&K}$s`aH$B+Hm3+J6`9~t5tZUtGrg&BsR*tr zibqRDWpJqo&NrtTEfx8~Nq~+g6O&41k6bc4rAN_Tv{*PDk5shd$KCQ?G(-Qev=frX z?M1JTUMb&qyMNWr){l6PY;)UvN$b}NnN*y)VJ1AWk{&G{!46U;^%Ue%St;zHI@?u- zOzJhZE0alel|rQG(EpZH-FNS!np-zS=WwYFGIyT_EF6Nj%Au_HCZZi4645s7TzR{Z z^3_iS-0=$T?6B!TQnd^uxp&;v=OiC5$>-3x(k)RPm$)vue_^z}uX=-bzrhDX(B8c) zv{2W>op45?ftqmQk~Fjj#{Po~B042wHR*<uD6^uo z;UUQUC;!=Uz(-DvDf8>)El*7(>Cw)XpQD8})6;_rYu!e92NmUmXggXE?LZ46CZ7it zL`JxdG#oQ}i@YE*u1_92S&Et8$#Z|V2|eeHILVww#N%vaoTO-#k`Jne4wshGM`qGH9LpS*Lj z3LOr(5=$m&BR;#lgXBe0i4$*0igqdaU=gZkyy;<+Od?iLSlUU+lkt>?>~_6;G2Qzi z*KKcfJMKPv_myLghs7HDUdco6d`jt{_rHqX5ko_krI{7w_ym&_$9_I2a-yzUkBxJdqQYn)z5l!tC!#AOA@unIs)GJFs|46=)T+9~>Q05br_VwJ+Bq9C+XGzTsf!Bs`%sGE<4+Q~c^D~>7ZzTAw) z)_eu+MazPFXk*ciAAd)C(SqS7@4i55vgDxc`Ffd+v1k4By_yGldoBpc{^d^(z5cWL z_NCta&kxr#vbJiO%ULbIFDa)ld~+jdUJ} zX9?$1)ZU)bDMlH?|7mhCLg%N`sW9N27I7asA$?rtqwu4RJ2P+WbTOd^@$ z-BAPF2^7vr8jd$IR^HLUbdi)!qFqSoWckFuPBT~B({-r!?!hi}B2sv)QOtkw60V?Y za+!95uE`4`LD%F4k)UgGgGlD7RIy=%I-3-@Z5NNO`HeifCXF@rzD4qIl|24->9x>L zqFxX}M>IaAutkJ*ok$^c#5ETaLPxw%jezR_3!x((%T@>-aSd06&=D_)D&^sBhJ?)Q zfl|!sPM&MNpZn_!^J#6{*k=xpzcX=gd08z?ZYT)f+y20w#p%p<%{<=W)XrSFh)@;b7qUjvGr7D74Dmw7VS}N1w5%KO)h9qUSE~+S13qyQX z9@eRRJ)Z@~0g#vcm7m_%qcvTOaCPx!GzPLvPTL$d)fhsai?QqG-ZCVqc-*%tbr_k} z4^%^swfwQjzJg5iN+=xm-?ejL-IeSR&D6t@hRrdsRKLy2E#I!O=9$tgu!#z3ak9rODof z@KNEyluCs>!g}PFO0jg4#QdrY{Q$wbfD$e;k2>SE8A~ z!RrsdximWCP|tL;_tpo$i~CmEs5nDW%%*EDb0!DHY&w@ZC1%rkOky#c&ZQ`d*>r9y z60_;tR3sC}w~m}MXbK8O4zuMb7O@`j1 z&745}4>pXVD=sWaf52)FC@Rn#jl)@9%?Mkj_7z_$`>mFgL0Jti%T$rIwCD~;SsCNp zc0Bre8m-v*TH>qiuMdBF*W4a3irvRbw2T=67er&w4is>}Zz@_4nc#vb zDQAKfYu^n<3+o|hxiJeZtmTfy2gFT(UXnZ|AD_G8->zOgc-i?uoimgNsc28a@=1VG z-WDdTycW4IVdXW-j57DQ`0O{gyJ$Vucy~Iw?c?~PQGZ$Ly5{49u-)s$t>K51QZ%0Fy3^gRS6W}Nd?04W>*7ysSDwhsVChrePl82=IJR&cB+3K&8qFYQ- z9CGx9!`I=4R%AN#Dt|nL!_!Dj9BX>+H8doIl7XDzUgOab>)j<+5?p`G6wvB9w}dFK z?|<5L=dDS0wDznUM>fKBlZ0+3@2IaOMFe59-sGzx*JfS$B)$tRXD*kQqLk+%1f%Kx z=wyzsDj!57Vu7{s(hR7aeNOox@9?k0vPI|2B|B zAeIUdoboH2EE3@bV9W@#T#$m+jx@^nWG4@Og&q+Bbic~nb|Eq7Pch`yH2<-6_r%V-=cBQyX76VgeAjN0q`a)sPPi=qj=f7I zFjfh_3T~H_Surbr?4rzoRcg(VSx7XAl{n&1W`yH_r=z8!GPqPU7>#ze?A0+bCMdS| z05mv32PYPD8SO<2hLh|55^c{PhPLPH;iO&%qV4(NaH$ARET#f275TxXB0X9v5)yh` z-71+9dcH?S6nB@t4s7jy_M`n7bIPZ9{HBMns>|HQ5xP3W$nHyYTV*=Ks3JdLuUe_2 zu&;VQR_9%(w4!{g7_L$$=?|>wIXDK} zSb1j|)5XLgt`ch@d|bBLZPixw$cS*r?;f;rc@^3bClW1V8sS)5|A7S9Me!r6uw|q6m{13rKRJ^<?P$5-l10 z5!i?)B~Qji9CEKwcOm`Whg`S4(e1eV?A`yv?o7;3*0DgDBhVlF6-^xn2iJjADUeG= zL~}>a66>aSFE*59n`Y85{)M2JUCbdzc8noT6pTh9)4|yoZ$=BE60{&<`=1=YSLKpZ5WEy9-1nz8)L6vF;(&$9o5cgU06MwCJY?wmPX*PMiSbh1rhTa;RHVa)o|n$ z%+3R=Q4KfO(hDt!OmIO2N4kxYpNR|!nR_Gde1A=+_xE>c^TE_kaSIJL!Ww`k;zkkxUcU|1MjQ+>^mp{wP{-S?cTAQ}n zOaB#>U9o%L&cD;=pU~%9zUZGmX86*1d)Pl5MgMRL{i7)QAJy!`P4wZo3FYT}rrb9^ z_$hLryL^tuETilop-@{3uvjx2-j3RkCuv3;8GFXyuxc}sVD+2 z6;X*}b1GUiEoakh89rXk`uy|r9e(N6quy)nwRus@ZMjDeQxm0ViCsiU%al%s3X{s` zj9P9_u$gAXIvw^X4zQN7f(X8CiUS4(2*H-0OFbnB&LyLjT`Jo+=LRySaWr?Dvkq2t z*jNwQ_NbaOEvKW4iKyz12v!Q|cU3rW;8|ci>+L75D$x5g@M3UMw7Ar6q zZF|(im7#Do794NV9=b$)w*SMD7nv~xzh_<=-BGG~E1|=8alz4w=qS%Yi+11C>21D= zQY6*b_@%yZWE{9-px~BzT#rDl=YoWlNA3+tFpvDu^U(goHt^j9@o{=Ei8eC$Y=~&~Pa@!g2(HeWf)+%0pk|@~H97inVqjj;f%$7tf}4xv_VV4wpE8u*n0(?g0Thw=%9&3E?}-5 zmH|eGJ%lD<%m#nO2$zZAYz+3I1yPwDL8Lnrdfrdt`eJMMXD+Rsl{qoZ+~-5j!GGWI zWs5hvT|Bx~AtaHGncHoWqih15Y=8_}7F?h+Tq7`+335{RjMAW8;|tO_GteN{*GCm7 zxXi9e-Nt{deK)UDBi2)Tt|)%j;M=l>QCz*xD*WF-Vs5J7`K59=&c<5sQoLldiW%s<)IFR{v;z%$_RY%bkfQ6wSt^z!w{#V{)w=BZ)^y( zZnF{OMBYX%$cfw_668c~5D9W3k0$*GBPZ7C9TXH+eDZ|QJ5WOF!MZX*oSMX`$!?;$ zoq7kSN$+4G(>rJz8)W|2`;LT<*Y4|(dvqP~7*DmYH|Jb8hhGcDQKcsT5^}kg=Q6Lr zJv8_wtdPP($|kBoa;+nD4-30IFTA*I6qC=b9^V+ByN1xKwh%*3RU)4=p8}~_L2U?C z=)jH8?=ADMnJ2gH@*ZUu5{I}-F68$7aoGdS7i^94`u?X~cix)hXiTx@Ah-#wqg-SM z0%KiOP6$zYrU-}JNSjVD~kag4|!m<@whn5?2(1Iuz zE{Nb<7-+Y#d7OBjfBrHl#G5*dTfQzT%*$Szp=4b*Q~0;@r}MK1Ujh?n(vNp8hU4{HnxN2 z#WH)%|DUeZRA3gdLX5y~(khGIt$zT6j_4d}y+V%8u*~mRD)nh(d$FeOWwAE&8 zliEIJ{w6H*3VS-XGXIoy_b<9E+)7k*S$Mqxd%7&`;;ud?kxa7B;9;Y3(<&=wDX4b> z_axz@_m-oPfrH^H_)TaPJQaC1lYy<vPm8R0S!9Na=OT37~E zk#Io-mxNY`aLfSD?7j$&U=pY`~1%CAMKuI4m0mO=Xsy^_xzsU zuLvy{xNs0}6* zWyX*#LQNK3Dqd>xln#Q8AlS|PA*}B@&A58U-6sS3_wbQOZEPDpgX?rTkkvdE)VT(2 zk96kPk`$3I)e~JlT|cE;l&{C_v`~vLa>8X|!&wCr6!SEQp(G6~2;mlmBtlC%7>0oGO>7 zNYI#fQ&lcebhHp|98{G{6g?`da*1MiOAbd0SA=k*$|Z_sBDfxT4Mz}>T;fzK!AA)9 ztt+qH+jF49!@I+Yh9duj5RX}8J9*mXm7`2wPl`5_c{{p`8v2JP^*&b?lcbjqoEhgam~-o?XC*DcuO zTRtJhA<^y1yy)8VL(+?)f_lymJ1F5L`rIMuKTCeMJfFezF1?C}#mV?3P5*$TrMir` zRC6Gg>MG(=oet_bQ_@2sPy968B{L(xHY;~z9ea{%Pu_i`r=~dUmHsIAjtP8=e4NwW z<9Cieo;9Uv=#S_A*SdKW;5yLVcSU89BSo?^DUl_T-tr=B)1+BfHE!Y=&DRuLNmHN&vxSMxyHwospFYH2V+eD*< zx(=>iOHx=^qyI^0L6n6SL~M2rtD_A!f4mN)ka7Yg!I8B)tiRR(Ds<7p(CP5@!Ix&-(vV_(ZGIZj#X=-$h7!XC9Dp6 ziw=$>3ukdl_zKoU8eDRk%fZ=N=31C#=dQJn*tX@BPUqHisy)1toZDVlKRN!uR05C0 zh`01mwEra*=EXLB=E_lA^acQh9)NDkb3^tW#+SToA!!A|9%c zoF~tQy_Id)bsRyYZPG>vC2fR#sx|`avRg{6M3vhS^9@$zc0`$s6u_$7PMZ(0Dz_sV zL_Bgk97N^Tldr0cAhs>(Wzt5NVSOfia{VI5N47n7{*R9q6<#3zpdxsO>ab%r$Ynv{ zS7Q1#_uMiDGf{%mM)of}YfmDnnZ}n8CU(RPQq5H79oX~B<||3;u12(&%*`6n;`<6O z>gh8SH&^;K`N3QNnEFY6%ex7Jwcv2`V5#@zX}+HBwg(&M(B(Yp=-^0YaL~qUXiYXa z2ZeqYxt#}(Zx!SZ;pp}oug6Wbj?~aVhf=b7%ukX@fSocS7Xh^X`eqKT} z+=$(FG-&Z7jvrH;cP!x*32-JifoK_FAsYIsgHr%XK}(uhaH;51v{bYfEfx90rJ?|| zR5S-I6&YruRk(-IQc*HoDxy;@R>SoZv{Yn-OGUwGsid4@xu%BHcOvKNom7KJ>tk_1+N4*DD(akvBCc>oGzQYa2@tGi+II@9k6ud$m&+vE^H}S6#97 zyLeXDGU$s9XP76{*!rzx6!*JQ>PZErY%4F%a=o4UDjf_O04G`Fg6q@8)n-uYvb+Lh zvmZacJcVsJa6!dda!^6_x?ez8NJ{aI>H)Et{(3)A)931!BHh4jEcZg$gKv zvSgmQf;hZ*siB$)zOcy&piFuwk4=zB|3Ja6h3f?$N5N-XTvB}K?TVWNZe*=g$aM`4 zdV%AD3`Q&F6G+z@%VA+A8h#fFhqNn*EXA+9!-7 z6FD^10iTz6)xY?Z?Ng(=YW65HQGmvG)WPZa?L=$6W^w>l;*1svugHQ6A~@6&juD!H z7DUNtL1ci-L}Vj_MJvul3!+N6AmYhH9)8EO`w7DIuHE*Hp_6_-X zVZ<1(DuwhS4ToZi$%jW7^#iE_n)=dj=V>i8Elwa)YpR!tG5f01&xUr+V`J=Ok)?=Y zgp@U_%+4sUB}o#fB{PJL%B~<;WJ{0#H~&EmK}n^QS?`F}QuPDz8^#tdWLRQran}yD zg63aVN-Q<4Nk;bN6I;3Npg_u+la#pJ%`)rJ`nO4b$FG{4=)m-RA#=hB#N9@Rn5eGt zBr4;liDNqmc2Yx6wg0RTX_?6)O`|Q&rJi07p27OHMp(&#f7*Ngi4u z!f`-pBpv z?dxNFW^N`%XaJj~keheLI_75k1}XFzns`u6&=*M|U18I@PzE_x z;QFzjqQNStACJYD9?~LA+qhKvi-Oj=8AO}l2En^UnzvI%sm=ho3gZfNRhkE zXNvf#!HLcvL7V9L2(91Zi6#`N+lwZ7eH<-_)}jTG3tA8v;4%@MZ{a6sK@6enHlM>VhyXtMeSx)TVXfn-Z?|T=cSxhP z+wM5v!of$cT?+I1&}#d}^YNNcSEVEmbfnUNhd|A52G$Yk+BDshZG<6vgMat-GWxqB*O_zatt>cF3j3$ zBUoz$>*B!Ds>8piBFb_nLF(h1n^{#6WwE8wt0Kx`DYh3{dQwG{MawEUGN&q{ESiaU zrim5VV>m^WHwZpjGE>;u>D!5J_0RvsD(cDA;ffS=r_l;JRa`)9z|5eE3$!7_($EH2 zOq!eWAAUFP|!ra%EV8ysR@3W7HIm1!kb z7eY&O!@55GxnGyz;gmDvmk*qecF=L=(XUpd(L5dv%o_~Xe1kL8DMTxev*3!qBskC< zEfpoerJ`|Ysi+rPDl)*i3|>P^Magif2#$;R4q7Vmhf77&ktvhC*WHdbkIA8aG+Ziz ztBOb*PO|a5A~Z5442OmHz>yKzRG_SU5}s#_J#|ir_7Yh?W=uh?W?acq}oL(snIH^zIpp=-soW z#g$sfBmZbIpGG_*Vi4pxKC3IrT60wf|<;Yx`fA`XvcnD59MlO$*qH zlBH$otmSPnku61MHPC=J9uqmEt);S*_5xF}!&|Bn$fY8kAL&bF*ul)(!!<(Wp6rTJ zKjqF2&KyXmtjbZ1>}nm{v6M&IMiD}^7g_~DLLON95AUFrG{-oYKb1=|`)ktNg*5l~ zucp-fZFI-cL5^0hv>zrg!3|6UPS#52wOeuis*D=q1ry}0L0z~h6z@6vbughfv{ zDC5EmN5efqG^`p$o@}W%y z;b@;fxJ$%1tNO5R9U_)Y**NI@=0j$17O8e>Kb4vK4R~%sto*}fIYkR3Ify0jGTB>DBGIwf7DKRZ=VRvtTikzF0&t)(Rcbg5VC-DR|%xYsBI$6-{^HEfpzni>lgM#6pWk z&&&YH@3V!Lkqaa@o@WLtX@ZdcKgHG04WFUyF-@~i3BXVbw;jP1HE@TA{b-djb-%Dq zpm5#vxf~_UGS@;HY;+`-h13$S`YBJ@J~gVVMv?A8G)J8y6>Dyju&aX$^_^(#j7&7J zB?~Ty;Pl(*S;3-j)9eeDPGT}z5E zdg5H|rS8u-&hFXiS2w0iIP4X9xp(of({&3r`Ib*eaY%H#GB3LJ{E+mbsGy$n!w#Nu zs@@^xCFMaqXG(v!JfFejE(ZFNWiozAlRqG7sWKp!>Mg{jDuG<8HxZX=eu~3hbDrhQ zyB=EXA+J4o&(mI65FgNoRFWcnbEv2=9 zC{={}R+ZPL^c?8$@b2(TlEbHfXs=#c+iy|FXv7xuff}PxgsP?|@eeGv5S*CW0S?e{ zY)si?!BG&LPIq(E*cScdZU6e&Wg`b}Q{IF*2eF)NH0Y@h_@9 zqE7saWg@(Zf2T`mFsLUQJK|Li)Uk$XBMDAIn$z^^y1#XLEYfy{d!Z6O%`b9%NI8c4 zP3}STH>@71C)$ppc8x@3`{9NfcqHJrX1sSuqqW=aIN-vP$F5xp^Z3we`^NL}no!p& z5*JhgInq%BRl3F_wSRJ$c(dHl6m@aT;Gf|~ zul9Zw(0`bFqaG;*ZH;UbJ3(-JBo76oO|GQWbyF?Y#o|r1SQnim+Bs?w%##i zzZV1t!Rh7P6Jevq{n=OZ*f~YeF#6zFqwFMWj5RAtRAsC~dJ)HNq)1`xf>!nU!;SNC z5ZLsw%&E;z5F%%Ny!!jvQtz*(`FgtB9+b0f(0CZo!C8^PX_$V5_Vjt81-lMTVC^{C zp0XA#h**=lUXjf~;!T+mC>FsTPQvsPv>*zB3nI8ox~6xu8>rkB6KaPqBwX^&G0JuNQo}Ah)OUoMG!g@ zAh9_TB;w5^@@|EeifK&YEftkjcu^HC1*^UvR9C9`%#|3p7ZSZobsgKJte8T|igQ(E zMX4M@IiOfoS<$J!?e)*%*dW`!v&2IwqvK1i-sOlHlY7wD#HvG8WkpeTt*WeeS_EoR zl@&#Uh$jSdh2Uy?+`3qomJV&Dikr6J4 zc;*@vQ8h^?5)zi5x(+R@Uq%aSXAZY;2{^O(TlBA><;J(sf@mQ}5E(DbinS5K1;JXU z`R~}Ue&7Chho~i>u&T+r=-jnxvMxI8 zsG6*c77}pv`dKtSiE6Sgnu=7DbH<;4xWOhTVY2 zvPIkTJ>dZIU1$W5Bn~{9icXQdBH3T~er-%5b$C!CDL`<_l?hrI`k;+65edPHNC<nIU;CJ)9O(7}Z|+}IQuGh@{yaJt)bISQp^u7y|a+_kGCwr%;QNAGd+EGiphZMQne5NWTip?H0 z>OacbS5}o0MX4=ttw~iWQFI6etx{K&5=D84s#2m@CNjWfqErrIi(O3MM8XjSr}%F5 zPy4?hR6XRO9G1W;77;xQMYh*gZ)$)u-K7H?mP$<|)xMRonQpfFOSGe$`Vy_j7>yRz zIyeAGRqzrkmQ)2V(E$Ke!AmTNk~uPwp}{;MTq8s-&8|4GV7JrYZC10DV3|5|e8_fe z6XtIa7&TPF@6qVi)Cd(&a#4u}~YbEZPK^pY{SXMSD5R#_Ae_Q@r1dyMI*Nhk9*!uSn}^fq5As#@e*D!KH4+4v&fQqg#a^rg~IU>+-iwcxNmxis%< z1s&TtGF$6y7LMMHp5SsUk1V)K9nML53R;bogH}Lv4;%1dR~x`%%_5jb?ED z^U3e!pPH`Or-VQ<4_QJH9)bamwgrd$s&;2$^kf~$MXiA%+3Mi7xjks$Mm|~+_e5(P z>fo5#L{`B9>uDyp(9L|-n<86Svzxkb1ku0Qh}WOUDI5BxN=HUk(f@3nV z8k=EVd>_*fajBfC^&sbOck%ME-r1w{c?|G$BgU&F83BgL&XFC#3v?^wjZ^)D>9_P; zr!+xGbDH?m^gW?BANpoctXpr*I+G5*92e9Rh1h6{dZG}WZ&FVbVnM`nqG)zB5vO6A z_X@^%$Aa+TG>S{mj-??S$5Lg22oBr8n?mRD5nAC|xL)va6nwVrD(Mk)`|zy+H?mgR zzodkaxE_vR5`fmQ8qCojG7qn4XR|f|Zv1m58cPXou%#DT5c$Ie5nL}n7%dZxMhhY% zTo4hwhQ*iUnQL)yE$X$(!|^W>+g@7kv^XoS!mVRB&0CMWHq#@j-}0(PjvOBtW^xxJ z-5V#)a)NTBCku7uGfA>hOLz<=~_t| z-3lP*rOX6CIu=|bGf3Sc=eOPYjIhireBVm}N^UgdQjx3`-cor&E|qNB9&$=3XK^i+ z%k{WP)^=7Tp*(1#$4Aq9gw=b@9skLw4>hlt)mCrkG1Umyg@-HXm%$->a9%p8XlQID zoZP`Qv@_3oKQz0cmnm;zaZKSLvzurSnkU@&%RkW=lrzx)p#->zfXQee-a@!k1c#Yb zqopDjxKu>#MJzJ+6tq<250{E~{PQ@bHd{Zo%|S~=2DqxI0xcDVaHOJpdAF*!-V^5Cm7ibHUr&&`%98FHy08$ygfCOxVeeAfgY8gcGZQTwZ&105dT9ZoVD z@(aFG?O)onlDwtMSF-kseV&rU{{?h z5gQ5cgbQmpHn%!gA{In0XhEdTm54f3K2UQd|CT%Wdv?W8)qF`2qQ7}JRn-o9s%i)3 zg-YvCFpv2Xn>;jJ@Xbr^Fn)UX@$)vV`EuljjDD-P6jNP~Ms=MtYIEu0hl2H!=KoT>{ITnYyS(;U-q@KRuBe_dzN$EYE)1m$C)kCV zbRm>3^rj0d*oD{VLNHx$qYHKH!s~P)j4q@P{ATe4y0~`lOQ|t4K723qcP?9={-AzK zdEolResn#9u6xb+a79X7pV}aHm!p5Vl|7l>m`!gCrWcg#eL1h!u0`)V6y_6wCASx8 zS8OIh=%oP^PK!GeP7+vWB<2kdL76a(-5r>-6cZw?zyCe9e-~{+cv*A|eJyl!MQyo4wvM$u4kNcnr>nF#@PV$ydv6S?v z-)6P10&~|DguF@<9AL>)?h$o5-Am&qHc=QeAeV{;PVtsXDF$p)ph`8|x({5%_8V^T zaTS~5lL;Xk&(GRwBaonK`tXwK;9)bgJ*LU#%cA38VYl9d;lQO-YbH@_P_T8o)OOO6>es2KJ^=o zP+f)7a#hT%CohNgs}8OcbPDa1<4ICY-0dWet>2`c&>uxRnT|k9jtOv_S1+{QR1sP# zGQjDa=+RP<3tTEXf|iPgprs;zxK#88S}MwcOGR*1(OI-q6atru;LiVJ(Nd8SE)@|4 zRGvoNp2U>PlLvN88!&rAX43DTHFj903A?uF*PVX9@oU>fF*oYE`1Y|5O8b0bXz^!* ze0w`OOd0!P6TnKev*wbi{sjv^**d3g)|7I_4}C9&T(Vk!aTC~{bDzk{g*Bv8Wwz*K zC4Ii)D0zeej;gj5sa*%X;3Yure#gn-*|0WP^xU zq-Rrby)!oS*)e%zmW*A#{GZjKKNQ{A>X+B+ zcu7rl!H)Fg9qDxiOUCrh{G$Kr$8|rPi4GajZ|=x)zks73d!^P-TW;J^W!PPHVRzNd zSIg2*j7^C-u&V4IHMd4it(*7l8@H>bE?-*n#*E-qqx9uoM2O5CPn%@3|FPn6>c(aq z=p0k~__RqHD>tFLAPDxt9PdrD>=!SMD1Z8SK{$8D`VpZoU1$GsbZq#C;J3hg#7O67 zy>$WJy7z|6|HIoIg**R7BWQ&ItCD}zzLu@|;cq{EznuQLVfeo9+5ew5$<~g&T|@uX M(LaCFmu@foF9A4z#sB~S literal 0 HcmV?d00001 From 92fcac0cebe237b30c1c07c5174149f2fad1c2b5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 11:06:28 +0300 Subject: [PATCH 0287/1064] Added/Updated tests\bugs\gh_6609_test.py: Separated definition of max ratio thresholds according to FB fork ('standard', 'HQbird', 'RedDatabase'). --- tests/bugs/gh_6609_test.py | 59 ++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/tests/bugs/gh_6609_test.py b/tests/bugs/gh_6609_test.py index 1c9fa40f..2f31f847 100644 --- a/tests/bugs/gh_6609_test.py +++ b/tests/bugs/gh_6609_test.py @@ -19,6 +19,10 @@ 4.0.5.3099, mon$memo_used ratio for CS: 1.01; SS: 1.00 5.0.1.1399, mon$memo_used ratio for CS: 1.11; SS: 1.02 6.0.0.351, mon$memo_used ratio for CS: 1.11; SS: 1.02 + + [24.12.2024] pzotov + Separated definition of max ratio thresholds according to FB fork ('standard', 'HQbird', 'RedDatabase'). + Requested by Anton Zuev, RedBase. """ import pytest @@ -41,24 +45,49 @@ @pytest.mark.version('>=3.0.0') def test_1(act: Action, capsys): - #if act.platform == 'Windows': - # pytest.skip('Could not reproduce bug on Windows') - - if act.get_server_architecture() == 'SuperServer': - MON_QUERY = 'select mon$memory_used from mon$memory_usage where mon$stat_group = 0' - MAX_THRESHOLD = 1.10 - else: - MON_QUERY = """ - select m.mon$memory_used - from mon$attachments a - join mon$memory_usage m on a.mon$stat_id = m.mon$stat_id - where a.mon$attachment_id = current_connection and m.mon$stat_group = 1; - """ - MAX_THRESHOLD = 1.20 - mon_memo_beg = 1 mon_memo_end = 9999999 with act.db.connect() as con: + + # con.info.server_version output examples: + # Standard: 'WI-V6.3.2.1580 Firebird 5.0 7961de2' + # HQbird: 'WI-V6.3.2.1575 Firebird 5.0 HQbird' + # RedDatabase: 'LI-V6.3.2.0 RedDatabase 5.0 SNAPSHOT.15 ()' + # + fb_vers_txt = con.info.server_version + if 'RedDatabase' in fb_vers_txt: + fb_vers_key = 'red' + elif 'HQbird' in fb_vers_txt: + fb_vers_key = 'hqb' + else: + fb_vers_key = 'std' + + ############################### + ### T H R E S H O L D S ### + ############################### + # Requested by Anton Zuev, RedBase: + max_memo_ratios_map = { + ('std', 'SuperServer') : 1.1 + ,('hqb', 'SuperServer') : 1.1 + ,('red', 'SuperServer') : 1.1 + ,('std', 'Classic') : 1.20 + ,('hqb', 'Classic') : 1.20 + ,('red', 'Classic') : 1.30 + } + + fb_mode = act.get_server_architecture() + MAX_THRESHOLD = max_memo_ratios_map[ fb_vers_key, fb_mode] + + if fb_mode == 'SuperServer': + MON_QUERY = 'select mon$memory_used from mon$memory_usage where mon$stat_group = 0' + else: + MON_QUERY = """ + select m.mon$memory_used + from mon$attachments a + join mon$memory_usage m on a.mon$stat_id = m.mon$stat_id + where a.mon$attachment_id = current_connection and m.mon$stat_group = 1; + """ + cur = con.cursor() cur.execute(MON_QUERY) mon_memo_beg = int(cur.fetchone()[0]) From 996bba838b4fa80005a496132c820907dc6cc7b5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 14:15:34 +0300 Subject: [PATCH 0288/1064] Added/Updated files\gh_6915_hu_hu.zip: added .zip required by bugs/gh_6915_hu_hu_test.py --- files/gh_6915_hu_hu.zip | Bin 0 -> 1212025 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_6915_hu_hu.zip diff --git a/files/gh_6915_hu_hu.zip b/files/gh_6915_hu_hu.zip new file mode 100644 index 0000000000000000000000000000000000000000..974b17163f755e3b8625facc4471fe2da479f568 GIT binary patch literal 1212025 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≫Z|AOzRQ@7B?-Q!(N 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

V`LrhU`+ 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

$c1SV>y1Mwv8+t{0Zqt5Je1w++H4x&!d% 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

nwjk_D1=h_lEPz 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 z

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ðki7!HHIW`ELT+*B(BF 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

{(u!;j-Y7u8SDb)<&pi`8Z} z&!w%BXtfQ@iWtF=a&drZ_>19yo21);LVI!db3TL7`}PtYw)a+hufk4@E6OhBtza|9+DY07--`rI*}|0IX|qFsu)am1&MckR$-|8r zhyFOXuG?h2q9HZ%kf+4Ivz)RF@{*FLEWw}toY7tKj-FAGx;5DSr~c$Ni1; zOn>#7?^3~2udnG|Y8jo;tKc2hfkegJR2pnLm@%{5$+h}xF>FmFX0X^g|er0X!3npJ6f+R0V0>BUVujrPv9qUj-mIq&`bJA`^pM(6(t!W_e=@v|gmCI(vEDYY`I_CPF7(^1W?PyjZg*#ZHd%c# z>Q#H8Ikh-v*=5>Y_(N;*5dRhv@n3Yi1b^mW3u-Wj{eju8C&sN;SBG64+;s2U-2l_A zQe=>DR_Z5Bb0&2BWzLvk3z5HT)5(lpCo0zk$Y<2m`*clhT>#*jeT(gfCwDYr>(B)F z%KW?qg?eZBl)An)8(oWs)*j`MGKJY9y8zlT&JYQzd!k-`KL4jlX}Q^+5)D3Z#)~M} zsk(CQLI3e|eG~tHK7xi0V1mo?HI0j9HxR%7q*X-h{6}S+@YU zuOr{f_f(4f?Q_(8Jt2!}fMlJ?nAYs)eU-HGrS{WGc!9^#4y`Ytn!Kz%mm3J?z3wV! zyUpn0AsaVZR5T7GtrCg5#Kmxf?zqf%umXRhumJJwl-cC)gjxomx5@G@5&BM78MPSj z54TOOt5~Vh!JkqkoM_m$k>briP!d9IS}wEx+v(|U78~eiZ<0uSll_PQ%B&Ff=s^!{ zOwRY|jk|+y>D{snm_W5l=i~=vEe%6+e_h@s^G)`}|80(%H(r=7#}L@sz>xU+F5M>C zjsi#?>?3sUQ0cWinCWBtKvK!g&>Cq@iI%V@cBPyIJ4Oy!%%@os3ePGg5O;aL5gFh3 z@Z~Cz_gyB#iA}sl(+|dNvv}(m5Z7~DZ*wR7hO0pBP+~GhwsR5MoWG7y>X_Wf^+POl z2^I>pQu+7fNM2`zzxvx_84r2851ZX%!uMu{svR_2oZ6^G;s5O<)s^HvmzO6)kxRv# z*N%`zZVn?NY}q1@@aOwZ6M9ihaA-XHM_JPQ7$-I~zi?4I6M_|Lp;N7ZgF*tB6hVwP3Hp$(O!!tW@QQ!jRa$#wPv1uxe3Xpn|`41|VrVZO=@7cO|F zHx9m%+Dz@3Isfh(V|vk7YW5xY=|4gv|L|a&b%Io0JLeBlrsaE1{nfh$NMs(pDp}Py zQLedrBPPsR7#oEsM&hzds9qFp5Z&>5yt?U$$Im8(JodaeIr3XO`^!gSY_<0@?9x64 ziePbMN`oQ!dE}PH?C$G(#&BHMd7Jbp zBoke#?biDuwkjT_FAv%VxyNR@vdH3_Ik74+wgo?&jTfsrlcT7wg*f)W4gEN7fh{PW z#xQFcW7}h0!CWlwKll?efs6K{K@UV4Hd^!elcG{8F;la2ey?(cLrHbxVk7P&_@8^O z+P#YuTkOC0P9@b8k8yKzZigROdP1~)f80R0;CAXOhYVSPX36+YgUl3r^DkQhO6vsn zp zPy3F7i4U*il2w^y3YRyHc1AP!fAxkjCQ4ktJeTo!PQk8x{)KX$HjrH1H}f0czKs6J z!Q^NYyJ4ldbGODrn-{43Uo-t@qxx-!=-cUtb$m?b*~OSPj2Fj!&EnW;Y%X74BR0AG zI@i6n)8;^O-XAGd3|NS&Y6VOFX(A=NYrsRr0((Te8MqG)+3_NZd2?=-RzZa8c%&`O%yD z25dcYvEynY1jB+(|GCU6X*zT}Si@?oth{RWjs&ZTlTT|5Mu?KDX$GbwIHJgDIkSuhjY-YUc18iPH~pa>I|V>;Lg?L&iv z;#s@L6`tlRtLfnECRFS{>mhI z!M?q@r>Ye)g0~2p^P^dH3#8xkUu1LT?Jg7$Q7|SA%R0cbkAqn_&F|C-t0;kTVglEK zXO=lR#>W(~^*C+Ee{y|GYb=`|=NTM(s>3rrUL-Cvn2|kPEBy(7;_RZU+?cC9k6sE4 zbnD_+i&HjOO03#bs?*ob6U~yZy-C)KJ>arQl4n`pOUzds@?4F-SE1}Q(TmuY@S;l3Sg*PQ!u@sX2kLsdb%pFAWHx68Hl5ClULmy$MGX~p-U-es#S~>u0x!S##%@>|l3w!N`G+sUG81JTEN63?4t1*hE%1maLyh(0qL-fq z9g2UvwKoiBwq(%QeGg%hC)pLd$Q4v{CNzE{TLgd1Tb|vz6LCl5UPHd!i&B2TPP?uQ zNe%L;f*T9DMX{hQ%JT|~GI;3w(%!V2FHqALKPKw9S~lDoM)wF`=CC+zfPKIBs!mmM z{lqnST<62J?bL{!fZ}x9+rLkqgANYAWgnNU8gCNt{srBfvR~}vR z>-V}L)=`xYG9p24E1GUotJ~iiP9%vIy$&ah$CH_YYx>WiFT)~b00TSOsd^#JH6fxs zL@F#+b^nGYwq(YKmqH~HG^-k`JOseiL&zr~`imdqQD&5n8_DD6a16<4_>vz%_%75+ z502Sy9htWDMgDxDX~_MS@|@0UoH-x0$*rfL0^Xf@Fy|^waU?!#Zy!0`ZVONA6!(*` z>EO3^;CJGyk-uqWy`3?q$6)E9GyD!Ns`}AD>8x8E**-Z+YNsV^3d;vErf19ighQHm zi`bDGkk@GtZBQ^^mUDPe=ce+zbR*+_y@593MLpx*&E!%>kXEuD`AYE8PC^K_31=Fe zr-my+GFrm`kO$G)P0FIT+HNRymiUdhgQ$6xyMTFzZ(RkN<``6&9w zLMHUsBE}+nXDqJFU0rRl$fyP<##=U|IU$mQgWluk`+8r+0A^CPhgLcwX#Q`HJFNez z`^G{8_RY+y3q>aU2_1z^n5-*bDGj+!9ed+Z?M*xBoZM^MWLTay2c_NCZB{Mqu!C8; zDZ$PE;ir=IJ1)8;8-g@JLhV_yxzRSs!;nAb1HQBLEs%&jQZkI9&E6+kpHR1c&X@Uh z|M+pP8LFOc4{}eHUV85=MO7WW!NxMNEJnCO5pbY7=>A;F4a+`h55!&uOz^o}KznHS zF$?^hYiYN9K?;F34ZAMfUdMV7EWw&{fIk&9{+T$heXHA9-~!-!?Q2OjA1QMLh1S#Y zg|c(xgj~JBpZo88`eAZqoZ%*gCPWmmb%-@DTfC5FD!vJ=>*VsYy-zk0QhGDM!)KeA6hSg(|U@KlTLi^8amyQ|~r zi-+j9pf!aVy@lVa?u-2k?r$3O)4_2JVx-SU9smDi8;`ku%X?z$dBg&-+2YZT4Tso*Fe->%&;2Kp zR5Ih>b~cy%VAw_b<}Nj&fl1z=1-c(S%3q8azJ3A_Jxk=ENT?WIxrwiW?sIUqF0s=5 zS_aGXK5GJ-5lX*7xr>*^73kSYBQr3LU}9XK zsVnCH?#qsGAy=u)jG5Gk2;bRz8`r3b)3@fuVugkXt=`?93(Qos+$JgZg5Tktu?eIZ zLIjS7;W+^WSWjbuMG5e_%dTg3u1bFK5_AUmz!j9%q#PliS)VM;c4q`6T-TvO%-_xC zpxG~`BH5O+_YtcU5^k#^%P#0f8SV`zC&c$rgbl|^?Aiz~c{TYr{vJYQ_z*=C@Q24vzFT{Es7`11Z-(v--LW2V56o@ zMq+_`4hytKV-=^B=Y^I)%^}Wm`m!?vqasXL+S^bwE9hFO zr(eGU?nN7VYbx~?w|}p^)p^{bM5eGO&3#qZ-7w-78PSltuI$QK7gL!o*-!Y6me!oJ zfn9umdXjYk4~EOeLMvan^FN04M5XPJ{&*-jqACBIK6Tzr@&8yl_kX6_!2gGkvkoYS zsk^&W$|1>Vwp3CHb*r4u6{VaOc62N%r;bjIDdiA0lAJc1LzWyy4pZ1L3}YL^u!E29 z=kxs!-oIS$>+yJ9uh;YG4&Pn?sr{O!1eXOWKX%oSSlm%Yw9cZf9gg(I1kmRV8P;%S zpe+=uMo2V7)RL0-Jl@*VbW4mnVH6HLoZluR599+4BLK&#s_8gbek1lS5SggQ%gz0> z)+#6~^^t^DtY{C3$OUxO-Y+*R%GALpmyf$rv$e4b3o6W5*jBT#7LKV+cydH{oT+a5S zx5B0rASS@FomDn7mB6i2z3~ad8eal>=(v=WZ$?(7u$E1jwUF-YIue_Uh!x*{L;G{; zXl(|hu-LXB_L}FPYvrrfH_vc>V=Z=?;3Yi&MsNV0a93heG@;1@^MP42PI$L!q01{( z3=7hjxgXzJ)AQ#*jNQf%j$0oeb16RSp?p9)fh|_^wzpgD!RyWDI_7A`#`L6%o>@4( zsAexwG5x0ZJQ*K@X5j1I`59Sl-|u-@J@bcUUw@m)lBT@nL9iSGX6f_itgwcy z+F7h*$Z70GrlvuO9%k~20PP!MXvq&oec#Mlb%xAHQRIi7`5oX97Fi4lGi_qA;M%&$ z6Nn_a)VdhGh5K~xU#HPMfUYzuAB3f62c~T?>#jaGI8)9fZ6?B26scnZJ`1X|@>mjo z7b|@NpD{6d4IPl*NZAN^RXbY|bFuYd8ItG_|8?hY&tXgYR~Aw&+iBfBGdCSG|N18ny_&T)DSQRQuv-#ZRy=0 z_HwOlXV|=JKY-7`7YViPw5#)}j7?2V8nuqBLl5q~ti>K#*STdhdO)F&&6q5Y;}9nqFM z^8A1J^rZS;dt_aloi*AC`|36MJ0WHz2Xj5NJCK3$avS9Vsm5T+kAG{U09ahINP9|m z`*!~Kxa$ADJLjXM7M~%5PQra`Y+}%kZkaKEC@kxn^`=D1;8WVwbr1surJv8B$WEQ< zL;fY!T(IZQC|1mRk*uii*Q1YYp|bb>0JNYlkp;j@3;g4fXRSp=31l@_m+P{c5L>9( zxIP*BPfrGSYxAGbd@g2>PVq=++Ej86nA2OtwKn7E>GrE{wOO=pLV!hGlm~q_vS9CV zht|f!jv5wks#hVDz%NbG)>v=tR&_9l^DcU91r?+J;M4gr(uNTXldkT45ZXwHHayw4 zu1iacNJFU{E76h}DtK@}dXq5|*o`Q5G?RqZ>Cssmw!7(jm(DXQKcA@}05lm#1v>2v z{}tLR&eIiBd{`E9lih&%y%=+1`N#osYxs1e;g{qkck210F+oqM%i&(ay{jgz_0^`b z+((Dju__tb)6wtxf(kAP&*+q*^?74QptTSji2%(I10L}7+l(_6zqb*NXuU92^7$lpq1k zo9}$FmjjPKPNEPYC&PUhCpd31#~^^czSfq>GZ$PfxIt3uNf0$FpcIGdo=D*=daA>c z&I5qykEAHvsBWy_zB6qP%8&@I_u)!{!8fxa@-LQv+gP4F%ZfQ`X+@r|FfX{j`Mvg9 z{1k;nD1f>oz*g|hta=;o3{I_l_e^-c_M6hBLrP&MwL>A-iVFB*sEP(xGpq}h?q}Vf zC)yih)o<3&el9VlC7N*gUw%}%MgN6KeD7#}6ka`S*N-Z6tIG{pCExD1^vx#Pl7Nd4 zgTN~6z46u0>mQl!XYIr2U^?M%8p$DS;HRPcdj{fQO?m#iDH*FVZp`vMiQL9dFI|fUj_b367Y??| zQNFa6og%qBUDy0+qa>vmTyCY(SCw1@U?>S`0ad{VFCb0Rswij`K96?Yb;HbD`Th7q6M2I(z8E(&Nh@Fp~b{ZZ~vH#Lk?18KyQyIE$YP0P6Q&W%_Ws%fO z4~;8EOf~O-R=ge5r-zb=lCFOV4#a5i!jxU0*pElOc9f+dl0t{hc?OJF*T@4&hoYbU zm6=t_oV^bCQLzf}9)Eu;j9L^3%Znx2nGEA}x;}fxb_5*hQkd10dHhMu#FNa{jd5x2 zCSdzTnrF+2mCA*f!Sp^@MNc?!J+C!5j~!hrc6>Rq4RF!Mg^t&H=ii#Rz?EG4FaCZK zkG(_X*=Ft4$E`^yEz({Iq6+t(Y0OikH&8qj1Tc2#+>kI@Q$0NFv4Fc@K&~492saD+ zOkG)-}W>Kb{9mPk03<>y1qsi6s#Z}!%%K!94`0Brwj zZ_Ey2rg@$M3)gUElJ}E9FBe% zK-1ClH&#tT$#y-l+oh4GR8#bHDdJ^t7KxAt%L6DV;N^gJFV;T66?v$L%BZQB{`SR0 zXlCn-wfbkI16n0}@zHANvE@IG4}ek7f7>D>E?8RAJO(E?(vh?&Ycgvu`;a7OXW+R4 zS;@$3YH%EB0*T{%ZQ&%gL%bF8?Xd_0#eh#NIiWEgFtb$m!A=#Ps6tDD8mZCzNUxw- zBex4vf~*hR4=Lc?&)ci}Jdnq^D*TQUeE9*H48;B&Cn{P#N0Uuq=K+v3aMJM|7z0a} z7`vrhl?{W<`gu)NX~MsJ278q$litAFn-{%*IRoMeZhgOkxN${S9gX6dm*eD0Fj)(S z%oWsu;lj~5?w=$Yeg{7}z_+>dP^{PfxBgbrA33P~O!dwCp%tHZ!w`FGzzxd+&ja5(}0c%6$Q z13PQmwtkv|NZTs=k-TB;(F2&>`y@u0^i*Nxpepq}|4$$gO{qUCKz7B2d>j37Vsm-i zBe&_*>R*1VXNAE0f|J35?0`I1yZ#)1G5Xr#HU=PVaR9Ia4|+~rI8<9pLL9W(JI7RGibbDMPG33dzu0E^DOkod3snuZMMa63vdCx=~l86Mm+yhOQ+|NG!Mqi=f02@PK{Wk2{Wl-aNy(d^4K>T z4OkbI$QQMo_ecKb^);NG>WWhcQ-0Yu%HMoo2kt)4`4G03Hq~;w%LTw#?5Ob#J%>Nn zMcGh1VxcvZIKw=_MX~O(W?_kqHU%M0C=XK+oiFhBv0G>u5_qSuF?;8EYjt0H4&~>E zJ6^Rbm(qFL)>JY6^a4uyTl#*dFc218?M>e4fckku2w?L+xpu8ItZHWs)o9?hYB_Jv zrG4g3&D7)16s(T=v>ZwrjT9eMh>#`)o;nM2Wa1Z2QaT0FBCB5$PsCO|PCnEm=&+$} z?%)$+{Nk!atjky=P=Q{t)!(roJ6`JuGWTxJ*(}J}l%W^Uxbvasi&`_C4<;Tn-qjWTJug*eu zyDx^O$1CxX;~KhcR~L*=_3hRgdetKkjjmbB>cm`B4eb{UBDA*c?Y+Mw@H-xSLdPO- z_TI@qh(~-9FB-VS+X8_uRne^*wgv3V@P((@HgFYF?yGkQGfHVddk>Qv+FE79%wFJ0 z>$cx2pjfnNmzCiV%TG`o4U2$$7mNHozpWxe9I#|EO#fAbJIx7+VaN%2gLt+jUBFz1 zu~+F_l@j};U>x9$m)!vDdIy@i)CbG6dR!MW)6`Zh4ZRhgZ@78e9_rcZraNw4b;CNOnF2@y+Z&dk%nN0o& z$9h`x9l7=&U1BF*eMyvrvRRLE(%EhP(*pI7`SebBc6QO?Yg}Tm>m{}#fb~_|j(YPM z^S(D?E!W2uyxtn)N&W0&{^np2X;=ahK6<>A%BV5t2c*n8?F$N#h;|A$;m7e%v%SJ~2kk+xEJCf)%z6%D<{KlbUXe zW%2v+mDf@?W3G)==xBA&`w}hvdMd8Yx7X7$sl~kgWdV1a(o0vD@+%{qZuKXP;i{x& zB8@ntWc{TxNN93oQ-vVyT)9k-{J@jN^vThz6B%jc_iQE25@8?AbIMH{#b^dg$$d{) z2%!AXyu-fL(hD5>gCU>JNC*-4`%QhvEGa%x`@QnP)E|jZ>DnB6fCzYb;gL_R2yQy6 zXP$`={jB2`;y!z$rto3(`a-A8Ko^H~C3h!ev z(f5~v;w=CBc!?n_-EJpgW2d=tIJbMen_x^teF8uD_WEaK&hh%M7`1$}&(?8xr&d!v z2(uEAhMO(3Sd-^4v(d~9UMQ;Id-Q1Nb>~F*vkEoutibG`y|f&hL=R%$d! z{-?yP!-fg}5Pp_ix_a*+)`f^|R%QVF*)FtG(@xs0bLb0G>#$4{*2a&9wYf;}8Cc_a z&b5T%8J3QfzBZpujP=3%VZJ%Iw)7i#<~}zeQ##e&luBs&h8sKu`ouGFXwWB8YSlqf zD}P%yWGygDKm~jjdu>j*_zgPLGAtFG3Uzo2Smch$E+ZSsUB;hmSrez%UgQJn$ai=r zm_0okKY@JK-$`?ER(+8GMbAu5f{yms9-9l_ft5w`dMWO0pARbP@q5yj)bGE4H8hhV ztmdqo5`{$@UU}I1e+X^%;bL^3!qqy2gTDuO&rS)bct8J#;QQ(yB%$8mZfgHzeFaPR zB3lZFS)fX_bH<^!UVYy*%8I(J0Ywz84aexnJV>(8{u^spn@^x`bEbALe>hj+6b${4 zufS0`=24v|O52Fp#O4lzUknCs0!n5;be7>{f(kQj?p+6LzCMS?y^5!net+`<;iU!o z96E2>{4=&8ldWY@17&wJh6taCT{gDp9hRIpxyqO{9xt!@Rq5Dfp8EtUA@E$2odwQz zY9noX?H_(R=;{_~r{qXKs((~Q-ZV@JUK<8yqn6ii zTkt%ssGsaG7L~CZv?a}`WEs&J*>t(b>$g-8=Ztf5M^%ObB1B!VU&65=fskFrmPs`l zlhP`8wxAw=PDNOE29&-xriHQzA6S~XyELR@Senz z6Ax6|Z+?)%kDn_2Tgvh-31e@g&F|<=Zx-eyXRRi#=GURR*0ifBhdS1zWe_$%10N<1 z40M*3JyTIUi=qf>0?iL6!j;(_Gp?8I(76`rUKp1k;Vk;BUYd}%2mL~*O-yl`$Dnye_OMMMlgbY{B$Jn4)Lr$(chp<4w8{B>pda z)RtMsRzQqAFkLP~X<8qv$FY<;klGWVwQ-6W3Ul0BcUTAFwCQJQ*Ufj7OIF&r$$tO3 zY_LJY;o{*A%KEt5T)u2+?kv96`m8<|2S*o1KH4)d|AqT(Q##WqBe(>%fw0WlIn)1b z`0z#o=UsP05~LT%R+zpOla)EEf}+uNyki(VtLUmvVwFh0-n4@3=Bjl0R5|0$Yq}+L zX=MNIf8J(|9t{f3turM#GOMxg4$<9G5tG1qQQ*QM+VmL*QV(dkXHE6$&3rc359I7ZV)2#yV!NYw! z)(D#~#HSfEK3!?ys3E~8L-XQE2iJm$aP)>+mEqL2j_lT8fSO1p%AldP3%6Np1yl-K z)L2&qbwysvx=)xn1S>^Is%B20Z;&e<06TSON)qf>r)y8p_AZad85o!E=IeA!o$uk4 z|K#t8E`Nq-ChN5_x!EU>WJ{)@ZsB({hZ>n0sl1o3Zvm2k>{S5a1D{j(a?u7u2PPq<07uMWvfPm9CIvRvJGS1Le`@?fOgbzjGbd>3EH_G*lAJ)7 zRKn0Fk4t+#?!C1NfsKL3k!(@jj>#2Ym9zkL?0Z2^18oCf-Q>_ZwxmB+lCbUCJoW2K z1P+I)8TkNRDk9D%3J=)g6N3?&p({4-7iw8qiRP#!ulUwe@)9Ak=Xh>uUC zW60(%1X}-!b~PuhbrkSZZ-H+qTJEA`UH#2M#Jol4r^6YmLV)FuIEgoaN z@tnaPYXG2Aoon0#d_z5ab$#$U{n_~09*aEkf?zU_>63hvzmAEieG9z;?715sdO54O z#o`_@_6hvsiS;wJk?eF!lqdaLTjL!Y4c;<)_Su|;GH%JigWE@>J~!mvCV*5&pdOU$U9?Oi*`-hxk^^K&x6@hQBkEl0q zuDM-k+<=&-hU@RblrA~NG&#)}^WgK`Eiid!m^ah0LU5u~7bB2)yk4ZVwV{s_yw2@3 zl4%MqNgoeSC5Pu|w<9h<@ajzUe**u$EG z<6Oi~{#b*-wC+6n*q=z%Z3m<{S|rxm1h$r9-^CU=#KoQJ{9S1fk)*aRf$ZszL5^?S zO(Cm=*-H)|exRxMZQIu_Z1_9%-w# z^6OLii>(kF1NGi?Z;s6mM8iRB$n-Qy?Bn5cGY+v+yX;`ngljw`{y~Iv?`9IeK-1+9 zfH(%>^qsF?DD>i^d*&mL8ViBCJt!$n=$Q=q@yWPW?=7!|>v3T1*x<3k&BsOE#QurJ zU#MMJgyd#c6mEvuMIXe(f-@2bhvC22YT+PRs%gTs7|rzakzI8X$&Tq47HCLW9O|k1 z4Q->qGrS@=S@;7p6B7Bc9hrQMVqeRww+a8)MO9lZ9q)%)JP)jrDDi< z-4_8`E$nlWapr|`1nV3dytwoaNY2_LPOA(*vkiYPN9;+cy;IPxShJS332WY1%>txL zn~$mi+$K!q!RVcwoI|HQ)j1u-v>uLx$H&;-coQ9Lsvvlh5;)o08>M z@=9?CfOC=B86XCSNU~pq{daUL3Qag)tt{TgvFpYttT~=Ai-YZ`2*G(w0Uzn~KjLE6 zM-2tJ-*U6ys1PD~&*b%=S@BN30rG1*+H~V`NJxeSfugp5MlPmU*JLvSlr^hnW2nG$ zHZjhDTyzeebeQMogU|( z#N@~^QRR2Yc;kR8L4u?0FVp#|6Yl*XQ%b0?rW4(BE{V<(9R8!iL>)Ske}x$s+?!ma z$;IpHZ+;V9gNPt9pjYFh~Z5$9|xYmfHuJ+T9EVc_mE@A8H zv4eZvrhJrnXSe8ZL)7;zOH$w@e+6Axk@mZ=KIJ=YkB#;rgIz=mG7mPHF^BuRqwHRr9-b>(;EurhAL3Iie;o<$T@&#k0EKu3u7N zND3wU_bv1uN_742TNQGv0n@(6Whg+M3`hW3HU*x*16x>Qx$2YRhB+M9#bp*h(>#93k zfTZ`PXrhg7_UY^@sS&mE z(~MU(MuNB*`^6bc@rszAqMQ60$!tS&u!oJJ0^vX(lFmELSxU%`-5*%PRA0Q>^UCvZ z(=#p8a)}l5%?7J1mFsV&pPk@0 zXE7a=&&)1D#_^x<44E75N(U(hEq!pavt;DA`qrql=bl1V1R2y_1$ zNg};gsDzf98_h-OT8$4MHIAZeN#?fz5YzsL_-#t-8k;ny6_y6HLWkH*g*t-CD?#LC zH*2tqjgRv{%84h&4UW^uB`JHP69ZY3HSjZ`Aygux z?WcFt*wz;FJB-Zq^YMzd0q7 zyE~$hF|qRVD|V~tnt9cfEh0zPDEWz1Dx8usGMY4CEkr?hrN*JW~~q5&2qEstRADS>KB5 z?gKuoII<~Uy9ZUZmM8m1%kG{P;4{cr?u zgmpRq6aJp^BNHpJOEBk(r>3k49DsnwqoLvonZ# z$3IfWt-{fUm=zJcJ}s)N)s0lJD|Su$*mVI__xU*f2Qre?hGKvnl+0wu6?Xl1G8ul0L{TV3nttgiUa0}`S5+{vts?H`Ft{AZhd zo!P_haw>Fq1OT_5r71`9kYCTfD4yOl0=!{U{C0L7%fy%mp8oV_zUm$}xfgcIwq9!B z;6e4*o6i{AX5T1$VN{R9)nD+;>HEU93}{9} zdN*Viw8I|!cmb&@;5}`VA&BQjeb#TUYAKoDx?T1gQEmCnX~Od;>^4APX=m`CVN{pJ z+v56)_PReCb!E-PZmHvt(aG$u^iXVHI(?Rp7Yr%N4lM@yv>sSKSLb|R=Gv7<+=dWA z!&fs(IYqI1EqiU?9SLXc5 zP$P^6&af4U$1wc`*(Cug5;|r~J+;vfB&$it%XV`e;)>=3VyKyWsmht!!G$~7g&K{< zzw~G!*g~ho7Ky?+-@Jh$&89w_fp7&2?B;on{pV;D$)!Z$7R z=;d4%e#UlVHUkbrXWTl?=e8Q0SlM;!%|HM)U(iX@>bQkEdOl5^yjp8{@4CNr#U(2t zPdmCznG}AUgg@f=#F|*!v6|yIYR?gtyj6lbz8Mrnqw?}B-vp1V&E`C%{ITEUJ0e`& z?~PZ7c-U@{d{g?jt5LFYoT=9q5qbHs29wrv5ltR5;Uo*GMRV+N3(SP=-{;<1VedoQs&Mqay&7Y~9?c7Dey7$SMhzSM zkoG11d~_=3zCGw{+XRn;W)z^V9oPV~wk>q&d1bJTzfAa`7sX%4Wzuq2TP}&|PA%F1 z>Iv4t(~`|G(o9TUw-w)ezSBD;y2nPvP91*0**rJkwKwkMoK`a8Oq>@<HWk|2zJze`bi6zT_HT8;3 zM&>^pFoc6fd$q1^`)O2$K871?;@N7*3PZ$AQpJIx!TL2@6SWLfc>GbqKs}mn3a;J~ z?T-Z^FazBg@h1H8r10+1$E2q!56`VC<$gPRj<~(}nI3k2nYbW&!Gg#s8+Rr^r$V}| z%*8*qdM1L{vi{+5R13{bihIow8B8ne+PCQ801wvg36|5%%*7gc?gvTK6q@}ugav-UaPO6PCMBAOf$-0NJB zUEJa%Wb%g~(<#gf$TyplFfQu4PQi|p$+~dNyU!aJ$%$4&A1|7uA)Vy{SD5u2ha}5fJIsK8B5T0hBO8DA9KMtj?Cf$r-;jz=WlDZ zE?qc)h5`y>zqcEsbrylh0fT zunIx8ZCE!y#yj+<1 zY@xovP++8xSONL6L(Dzm>PY<_CcM1IWjyj8`Q<|JeQnzIr`CYKgNgm}->ACJ>I1Dj za5izVNy8cbRVPGO%UADBT5)REM_&eL01db~Z>ZcTFF~59NugV@)pA@Wd+lRVVT@~W zmHmw#1(W^1GA7NTxYnM)TLl`Ra>%H|)3e;}SPzb~qTmJe-7%Q~A^_$)$O`XxB=7FmN*AUOw=BVPVDG&(*uk3l?C)j*_eebE>KRf9=zblS@ z4r3CYa(tmQ6QC!{)cHpZe00z6meuN4p)^shfGDrEtzL>Ac=Y^&)*55E{6w9FpbmGA zb>yJ{paQ3G9Z;u8kx!R3C~j8EUGGf{=hdXz500C?YW*Nnyk=r;$?;JS8rhNzG~LP! z$lvy_hOmk9w6YOVHvfB)!rgVyw`k{PiN`z-TX%LGA`xaY(-FRK_bCX>xQs87{4Nz9 zODc9nYjx!j+HbTNix2pmnP@bi6p#!fK>ro!Dww_*)nV57WPqtPburh=PW2uC5Dk3| zu00>9IdfQ%+og zs;4!mj8t@is1!!(rQZaVZV=>+8h!N{Ak*RGFMP;juH?84C)kx2 zq=FQszA~H~&-qwNCz(B7K4rG_HCHzh&`dh8nQH%lo=5Z_BPM3txn?{pA>_oVETh{4 z&2b+KG40fN9kUj?ma6{vhN`$(i`4BHE2vW z)r~ytiM(LgXQcfQAXFY?=F!W2?`_nrd3;3drl&-{f42OjuBe7_WrkngdmSM58TZ)L z_7!`mt|v_eE=Rhc6fUrbwwP|M)tQ@8tvU77Qmu76>?8&SGM@(X%%h20=H<=nhtDR@ zi#%~=?`DhgR(}1B$eGaDrJ+nOd+^R&rPZpnTQgbcY(f%A!$0oOk9O$wfYmFe- zjOp~+qD;gMQTlRK9KD#e`4^pGzP-;=2B}nGCnTYZJHU$55-fZo6E;8cEewSD^Wlp4 zy~V2Nz|o)an1vCIfeRqw7)l&CT&!JO#(QzA>s5=6W?e1W#Fg46*G76F``9x!mH#7H zbGvuk7)Ez?w(p1-Oy;-ohW{D+$K51Cp7Z z%n&OZ1EmbRp>S;rhq->!9t;}+XnrR+AY1=c=ot1sm->X|EJjGz`IdOdEL#eElu!XJ zB*Yl63J@TxB0KOP!MqBVhv^&g{K9)@k+EY~V!-Qkq$6_=S2W5j)LQTelpPB6PYvBM zDbK9Ex>BdGd~cp&{ihMzd;X$TyDMoU!qcoGF-3l}lrnMa>b*^MBamFhmLU50c(bvt zPL~BT>LH4TgnA!jl3Y7^1CiL4PWp-G4$26&v^yhPrT(6NdEvTV+yVJ6z_Mu13mYAb z_ZgKGdK^_$Xz`x4bAhtUd*q>l_`n0Xc>KRD_EQZHs(@n_*Jv$_72R& z6q+CCOfaTYY!i*XEiA!!4amiTs`H%|&jQ5OOu2!1q$94R2wr1w+e-iU`6s41mYMW; zNY~BwQ0{c00(YmkeLkhEIr>%Xvo>hD94GtAwP2f#+#vi^RXpTe$HvU+e|VYj%5+HL zDs6T`wDAwywKa*tho`6zVu}QRP>&9`o!%LCqj2#pcO5x%Sx0l(S8F`FF8z9Qm6Y-6 z(Z(l;=n;d7=pD!hsntD#>(;qHRh?A?t3fpPHkK6{R$!)tN|$GwJ;P0GRfqa8?+C=~ zTyv!FB?jqi*o|$s4+rH>_S*zrk<;6|nFaHbW0IIA^gb;Q?w|P4{&0Nyfu!nz zXvpZ5*O*ZT9QU*W@?#87*KJwe0g4$-R8F0#wLUXDrV_P!4bapR`lN2mCFpp}NDs(t zx*K()+3U$!omtZ>?BA#9QrXvj+Fy(wt{M<%a}rU%Ku5wnSerX~M}GMdy^@Q3Z?kq8 z-WWDSz(m z4`x{;&^e~-k?7AoG(Igkku!#R$Ga#ivI8ZL{c6-H%q;x@UsxO_pCfb&`n&@X3W5KN z`E)zKe>?U5U(Bb->s|6+e<$OAw?(7&S)AB+j-=HX&fE>zdf!+J6%P|9>FjUX`JIC9 z`lf75C$5CyNiUVEg^iJA*u8rf0;Mu{hTWAFB<%ma3es8NHJknN^p%S3@a+UP(hAB{ znhr%CwM-(mVD^J73cJVAe|BRgEy^G-G{T^Y!PW!ZB-4_TrE?j(^X-9AtOi_n@Dc?Q z9P!5RtV>+~4jS&9wNbI(;0>#!ztPg|_JQfb)Q3ME93!5K{vKRWrotR#Jo+F!Q+J3$ z^_+RxN{~{x4(~8Dbps~wjIDP^brm6F1_jS-EyuRS*kb=#%Dv^&i&qopaYPKfb5g%`E)WQW%v)Px*t1tJ>der{KAiN>MFrq ztZywvSYw8-G!?0>0Cn5eBZK%C9&I+`Q5Y*pp`Af7cVl1$|D5@X#>0(k?H|$&C_Jij zvn1F$ZNd{*Y$L8!Rq^opRCsA^dcmMHw6uF2T`uUC@%~&03XPu`WFq*icXuuJN$t-* ztuxHa7lE2=kbTJZMM&qV*&7>Mc|=OXckA`flGb$-gt*#wOgU=f;3ItUw&c*qbicyeVmVbn^9hj;dop-tp5>Wb^vbM_2~HNPIiSiR^P z{gV-|>r!c3jayy+__@fsJd3$sB6eZaqsNZL{2(Y&&)ZL$(^*iMp@8 zMLyk}?O|2B*$~>hJ{Xwvk3}ZueXNVL0U)ADryR{Xeb@iumc~#ZggD${dGu(f?Vyng zq~7HRvM-AlN&uUBGlQ!@&X(&NdW<%CAP3CX&rxCs`$c1TCacD_eWH#Y7CT6h=V^PAN%?SA@Ug`ZqkwP)*-r*Y4%<=YeLy6XZmop%GCo zJiJ>dG2tbN)b|aD8yRAnhFw$UU;R<+jazZ&3GtB?!z@!lRq>DAeWt6qPsmy~LiG5F z7K#bf49P&YP|RBYBnU+&%BcG0NfP#Pvks-Ej?{rex4?13n{IjU_B`Z=jhz=AeD3kE zL!uP4r=k`9a2^N}_k44%p+gOUUPp>x;RaW0-r?Kv3sssKo2rqLkFO>|+GJW`Ib8=7AU3Q#_~WE4{<(OPp|Yp{BdAC6ML-<%b6 zYRwjTM>Wf4)Cu+)lObKD&~{fMU$rFf>7*28)r(v)4aCFl#Vbn=X`DtZa++xU%bo#E z84UXCH8h6NJ@Sx)f-;{|-q=L3n{( z0!=0aQSh1yk*JaXP9mmnr%VgXa;Pey6c~CsgoyF}q212Cws6QaEbS8g_;~b$ z&zXg1dHPDIHx4F-t9GP)k!&uferE=yj{%&gbOAEne^j$)W>U?rIAdPBx*P55BZ zHkWHhk~Lh$>e8L>HMO%ZV*i8^oo=0cH|@SFD908~1r(YWg>1px3_iI67VB|*$Z3=N z8}&mk@EbD%`OW6yrAI2!?c9(re_UGhQtH9yXD1^l5v@c-BBx7gdd`dFH`S^kkYxCHida#QIC+QI-Yq2AQZ-y)Ge44=b%1 zMslt#WYwI?b(0eACI9=%vg09+76_FNG!Gkj*kg^r&w;)cF#W1tFsPD&1W5lqA?qRH z$o~5!63qu}g09lsqlOCTM|cVnieU$%F6I{{Y}l7{ z?_Ac|qO2Kfa(%$4p_?nEO{2kt%%pJGkH+aU3Vwtxj{T{>OV`qiQ}eRYpR>m=n{!s9 z!|7W08t2ffZa0Z8X8`U^qm24?`x#?5gQm4e zhcLf8XHJY}$--U%%^r8rKmbk#9&zQh*8jD;1Ho%gZo$v*a#_QE|NDAfS|T+%l)Xx> zJcdJX>tpEqa4?X3lPvsPRl{rEZjFs?;or^$&4`1{I-8k5s)hKVqq(aFf1Azr$cMgB znsc0FxcOJ;y+LycLgCBHUf`7Z`Uxt$P{o*I=329+FJ-RHTmcsq*D673;vsgLcj_A# z=--~COiib%g-v)5Cw>)+xFO;s2UFlP-3fldmS*R39`C5q-(#v~J13oM<*bL*@Q35; zQtGcA4(wyDC)QYlGt@jgiFqs-g>U-202@=~^EZr2>xr>**uQWuj7H^#$$DO)fsc!STRmCMbu1?A8>d# zQsP6Egnv!F9}$vt`Bdd)AOE#T-rt$(@pX#&;+{qf-Ur0gc2wFYg8JobQ;7N7!oQjajfGMUSmUu*W=fey4lKPBG+|W44Z_A^V=Q}l) zmm6bBUzDvgV;_|`i9MZ@9dE}(DKEUOSoF`Y0*@4#Mibw}E%uwje5^iT=Cv=}MK-oJ z#&^m*KBoP~$0RnJKj@Qt{F5t^K$O$``aEAO^q@JN8h;8!Piuz!TLuxJc);e>JNTHs z0w?*=jb=KW-3e0GWu=#T-|8!;-51wTOw%-#;J1O9%k|gSPw}E@S?0rfWsnL;Lji^> zPMhel&V1~Z=Q+wixcMhagsSC)M*_}pl8;!tL;*-u6UJ7Pmc0O7q<@jxOs5I#9o0o1 zzUzjF8tJ&ivy9eF3NhcFaPFHuR~X_3GKgxNt#8J&ryxDXXrePMW$D0k`6jb+g_%Ha z5#a`%iGi*rE3}e?9g#NUcZpt(pupQ!+#u{g&hoT}+Ng9R55`KZi&I+&u<;OSk`wdo)w*mq z>X*fb*WJ>ktf>*&jw)FllC^bRg9bf@ut#m8$97=J4Og%C$DWL=Mzi_gubN4RKzjT# zX~g=b&Wjb{W6VtB;@L_2jndV*QT`pM8)~h-5ZkEgG!JuvdYZZ**T_|(f#+5g5D>AK6&iyeO(o1!t!6`p0CAYq0MO$=`9Fv zU*|`dJVv;#kF01pF0@%38q-AH?v_snub;TwIfGS3I#jfVDcc}3F-w}rvZ=c~w}zpu z<3IOiAnvm^P7g@E;g3KrlEe3P?Z7Ycn$r6^VaMK2??iSCZu%)C_Xl{fs!zvNC$DS6 zWf#m|8yE8wVcwNKg1dql_mH?F$~=duMcdtGJA7{{ixYpG(aD8olTV@N$}GcKxxRHy zFcbnOJ$aGqEx=ZC9!=+`QPIpz82cJz{ardCNmMT zaP>-z$V41et=sBtQB)j9kH5!~T=GAbzT9}rPnU1H;aFclZ^hXOh_rJm_clbPPGc#AFQhZxa zTKOK36z`zk{P=WwrVIPq$s4!VU^$Y**Pcr}Fp?qJpuz&P zol39vEBI%Uasu*;O45@UTUzE*iA#T)bB!n!&E~D63Zq^WfzDnfR`PHs;|p-8g*YhG zC8Sg1Rzbfbu+9F50@ohly`R$(xFrG+1~XUru2-RRsxe(k>3#|#)HkN6^wR&3bncH# z_kY}X2qAQG$Y~wEa+QSSY?fT5E=fleHsy+=Nc)s9uma?@vy}YF2}o zyW-a_WcnTy1sz>66gNo~L-tBP8e6s1Ji^*img5F4lS`OsaGS~&~NxERJHT#abZ>DVmwa~85 z)D$umO-{&gDDx70edY$QA7vN4u#HR^eXdt?zVi$N_v1RJZG^ypUC_ZskNb9Qs3#J? z$heCwAjnl4nO|J|zhjUH>7D;oRJbeEUfz`ON) z0H9>^bLQmZJk%)S1qe0^o3c^e3r4EpmpHn9a|uH5O|8|FoyQfSS4}JE$=Zii` zY^p;+=zpU4v&6tOd7V;iT^}*Bk)*@O}@!1W(+C(Ic-L~glysOkY+<=*F9I7*qBe9ADE-_v>@Ky{?cc1I52`0njJ`H=UFcM? zhomW5;22E&Qr1o+eJr%1ClcaJ-SxyvkdsxQs3FI$eZ9fkx!@!Fjf5Ls(o* ze@%-Yv^kJTyk_k1LE!r@>P^IvW5m-GYPnO2SReuhF_|0kM3YJ7`G`jqlWI$*`K)E# zhGuXw6iM3hk(9pjATd>gF_+KPuzpA}wV3|jDdI7uMSmzxwq`XrelsX*Ys2r9jx9uQ zXQ9ioy?4L+%XSd9dSl_vBxrPfDo+>#61u9v zvSUg$GYM%Y$oKXgH0*_>B0gX;BCN&I0!_nng9d+7FXQ5!l8cp$PfFZV3v_3&30NXO zDAFyS2e9A3H~-AMfNR5DJQ+`xr6ZAx@Nqvp37 zzF=s-3{e_?CU;3sQT;wLp`qF>LMJ+Ro`CnwJgCv8cF3)c{@_aiZ%mX;!y(+RBrsEb zZa9KsYSR!3?-KJ(lL^V=Q@>OQYz5N?Kw;6S0$H}wP(#1@Sxb8kddg#a$vS5R-bJt( ztoR?cj}9H^zv~KON38Yt1&^V*cPA;ZAfEY!MQSute_%=leCaQALh`%ExmyU@%=l)i zaaaKVi?&QBgsCN5bRU+P#9f{CYwo<^7HF#_fAii6-$i;CvX5&^OVP)TWuZCmlJ+Jo zR3nHw8y6F6xKKAUdK`XPoAe?2Y#NCxU2VJVyKRc2NJe&g+#yQa7+uOghh&LIoyD1k zu4Vvc5;9a{M52q`-_ykW^hJq3=}Y)Q&xF|WTTb_@&h)K$H`sg!E*%K;qW^{oJ{sDI zpXz@bqlFwM(bfvn3vl9TFLsqi{_(QnOZ;ebUnVGE@AYo7h2*Y z9Lk3vIFn%4PqgJT8*k}Df?~)I12gAFoVcCVp+J4QPusmet|nZug}Y;yM$$^gI-3)D zYW+#mBIiOIY(>_Wrc~oGkHL3RBL{Mzb3ShoaGJ?$%UMK9qb>A&z9E|Dc_N}9_O3Y&0j9>dn@G$_)0#WpPQZq@Ua)| zjK7IF5ra!|hKClzK|4;0YBrVW>X0Tf7gTdFXrBugt=iON(kO`}Wp*h6wxH&E1$X zs)|VG@$9onz`dd_6~6Ln;8&pV+Bw-;f$iiqj5$>%1No2Zg;=oP{QjAbw=)c{0b6!$ zXO*d{F}}_~uSQC&=(Tt!5oDPZ^glOgKSP^;E34-kii|fArxb;__sw_EWj_+u);w?+ zrSi=1pa%OI|M$baw z#!%wSG>nH>X!ZZ6=htYxZ1wLZ1F9m7M$kAq58(0sdYtorlicf(6B`e{+Y+wUEP!&& zf;;nWNhz|H$;gBfvd~FmvteSReLGxr`Tdpve{qe1Uxz{Y*natGN2@od4)BiQu3bIg zHeXJ)?Boa<8ti)EhvAcG%2aLB_Gu6J{m+Xt{tM5!pBm@h=Gvb>na{ZQoqToB?|R5? z&gO@;G!9uwAb8SbJ6t2=yu^vRH5wd$J$&-Mow10UlIiq{EXy-3hJ+kmJ#ecj$+k6Q zGLu{Bo!S=0BQ{Lb$aaYB85h+gKz#fS08`Y2*Hn;e1PfgqBuCl*nz#@#KOwP+LU?SF|7xrLH2 z?zl1J-x%3=;?S;Se3=?+1$_1P4)+}8cGxAz;oh4x%Vung(KpdS~j{^jDP z+nf&?F0BXB+h?;+fQPt>fbZS&o$oU`tjk;uiuaW?O&6mMiV^)Y>qYFn?QT`9=X+#g z!>#@Zkr|yEqRq7E3eSwD5u$b1o&(~peZ#SDM{r>S33-~1dQqNkV%6PIXR6;(g+C*j zc(s;)T$`WEw?iT>ToSMTu2}j0V$OtRGmZ-Mj689ewBmZ^sCY&?rm?W@MYu(D7?o}; zhzlLZ&rcZ-2(5-3AKzi`zWrbu^ts_%1sGbK85+LsTy0 zReGGOSE}1RR_l{ByN}OVV|*rG@b0AccE^|0mtg)|P>Ip6cJSt27K%Hxcs?v9toHqi z#(bFElIcm#@^HT9hX4EAFYW~)4-73HSus_o9GTjo7z%ST=Y+R654o%odWvYxeuL>Q z#qk=qFGu6*@7{YwDVE8{-}btnni!fc)+M&{c%Rpkw$EHQ-K19?o*qNV$?uE@qw#dR zRvkp)mpiTOg~a=ZtM17E#nUoezgeFSiN{B%P9BJURrM#b3xAIM89wDY^ikD{dNY%_`JgJ^6_(twS2NOXS531F{x}UI5uT4 z?F5rq{Qg-~gO6Hxy-o-^ihDYnno#pvc;e(r3>6TxSZ-g0>!xvaCwltjVDgd+@uk!>&%`jzW%bvqIb0Gzq>HJ3DDM49d#tQBJ+ofk(x_@~ za`&!**bVzMc&8A&MS7%m2ms$$_ts{w2bI@Ws=?Kf~^-G->ltK*5 zlT;{yF?)Go3u1-}L21pSlgRJ{i(B}@vzEY)%xFc|$htcTK692}a{NBf;{SZ`8Opz5 z4nhN37(tEy5DwI@y1L>9T=(_b_!>GHE%z1^?B*S!zS-JOqof3|2@t5w3>++*EtoMg z_UJyGZs;;O-d#`8Mt|!v{S%?jk5~v;O*=`l9?Vjc#i_OBfQ#n{|DE&MPkB=m-l#GWXi)Wt7ZoquL1R7_hU{m)W)LfFki;d z=d=frR~D6t{3`JVw^F69U5cIT$ZXRk^aR@SM$^f|_@OGYJQNe-*4YM>9dE|uY!cv4B!1~6;M;h71%{NxKRim z6>@^AEYSXAZAf#{Bqh%k+8Dp9`i^gIcf=#Z<kKelBw#1c64m5MH~W-PdjJknrr_VGyfjdNQ&77N00>Hm}{Bt&*% zP^}|(A++Fvja=EvPOa`c>!mU_KNw^G`35n3c{ZlWFp|sHEJ@93DgrU5up+n#aG^{{*+Z9!pFicP~z$ zOr_Qbp=!?bioH6~L7vxo?%4+E2~-9_i_V3}5`8B*x1_Bn@s^0fs(OwJq(u78t|)q_ zb#%gD$(4Hn%Tgj5EDNuqI;jQjVE5R+e6$f{UirpcVhM_cSl!vjOs%h$7}ZWM@HK)j zPANON<|EpJB`QmPwNuj{M<}_K!JddqyL4t7q)z1JztqL zF2Gp*hKpdm8nLeiIb!28n*zd;i4KVuQyiR&X41#Ys3s;w;xRbhv zV*qtEuYUXU7i@m_?0Yk(<==s%OrNO)`>KQoTQ8fAJQ6d^@fHQ&M&m#($wIyJ>l9mh z(+6$-vc@EWYFDbQ_Mg;-w5`Fbn~tOgj_A}?P){n4}SAUQ;724*AnKv{9v zK}n&BK~>4q9j|lD{y3W?0`kgFMV%GyiCa6Ph<_plY})2reU`FXiHL=6RtDPX5ri7+ zj#_ohGHduU>LqS_kd~mfo(J9aCcN>L+kY$|5HLRYK6VqEdi;BA_O4Fm`_!r)#0j*g zmPm=f#uA0=>n9E3a6e#>T{(PL-)O@A(UIt&Q$UdbWMTccB4{t-YKo3i=>*nr8>LDZ zGy@YPA-_Zy32o`JY|TKIV90h%U*QVYVD@ZA;Zn&>oDp|U&5J!m0F5N#gs zG5|H04VQo|?oS^9-0QYMnVRQ+zqglyW7Q?{4mbJG-p51}#fmNob46h-ov2HEq`ZdC zcnqSU`qoYd>wUAvsu)Q7ims&An%x{44x=LOx`FQw*=_L{OQDe%P6Q!2iI#`12Px43B9vtUdaEf1Iv zE*5pXN~LHe!5=jAg=ljOelfb+q8NEyoD2PA+m_=S6c}>nFA4PSxy_CaHfeKVe4nJU zmKeyES|)!n`)M)o7~V|mT%(>1>SmOo>zCl^dCtzz zECkOQ|Nf6f(T4i6i|f(92E*FBV~7u0_Q;DVl4~wv!cAc4&FnnxAM+3|+9?yyE8W+& zF79DH7r`EmvniI7Qa!ZOx5%SY@(kcV{a4#@k4K4=@EyhxS~Oa6|2~UY==wQ6?d)}w z%+6$XXCP|;Nx~EVD|7k^48i2VOvah3C2*BkS?#7h336A=$lwcr##PSi9S z9|zer7~01_+moF)^+(BZLm;hZ#G|^g8oh8$RstX)|)LC&f`{q$jSO(Vu{YvED79s}-ik!UlF*)Il z%VFaJ`4eI5-^cao(K5ijIFW^loi{ht1#t3RFW+`S3#A>?`S-?XSeSyJPZF!Gl~M0h zi0Fmsg&%KL^t_mQ%6Q>3Ery*;<+R=GU4iF`rA9Pb#L#mQHdhFPGv+zp7W!D(rr;+X ziD%WCzb-B65f(zc(^`H;vvmnizIR9`TmEYGI9e~|8fs42(xGOZ&Z%g%X_v!-?)01+ z$dFTr$!P03hyJQ5=7+uDRX7-7t@t!K*`fCEw7$_s)writ#WyA1Nd)8PPesl#i=vnQ zmG~1nA|9N_2fE#Eg_x38_M-*+;t!51Pb|E*W0afhwV6<{9!bHQ8IHg zCt{sVccP@o-u}z@9asRz9uk*QEfo2Y+!+G}vKsO9tQ{4J+iG(zCH+#kkt}hK8p5Jb z>?(P^A_qqDI4h?niJ|(CdsZ>_iee%j%md z;n(koHsO7#sWbZ^mUdSVvYlK{W8jL7V~l&%;jSZ3i`Q7Z^Uwdc`Da#;Z_uHURYg1g zDSuql(UaG7A@GC(@~O0VUv`=dg;r!x&aJCky&P|QvRXUuLJNysDFf1-)A|A_#v4mI zrwBb$vMn<$=lJOqU+nO`--lXfoGhmc)7D>BVG>Jbfm;vNK$%>0O@SD$;q%Kr#)RJq z!^3k(C)8FQIj2gZqd5I6{InGaIG=@p7TY6VffLz?)kA*dh<>fDPC_9pe4!2 zn6|&yx~W>5ofQH;zAd@W&dilg!u#kfO4CZUel#0LzWjw>ZbzKL>y_|t=)jgW!*f2f zeDFSrB|O-9N|?jqD=p3@r^0Z#>xk8~>waMUw^APxP1E?1S{vvFs@9!$zd*C;Hrj|V@&fYT$Ag(DNuKt0`cvY8Y(jNiCd!M0sXj>f3ju3yyP7|64#~@Kqo!TG8#81 zZ8zc2pCit&>y_JcY|ho;?C^WyKUQ%XMn9S#W4O()5&$Y+#lJ&!+?51bXhJ(ENKUgJP0O=(E#K9G_)3G%`>( zcneMULOoa zp#FFKAnj1AkHN3vnErao3AkH4Cq~KTWPE%$vBdo2!d40FLDPp${lJ-yk@b;QZA1JwQiWoP+hWead8BsLRFg1GUYKwszeT0?mP{9BT<4?M zaT3+<95ye=mVA!#dDa_t3i!LtZAUSdvV@FC&LBa~Y0bv_#0b}8+6 z<4!idStL&A)^xlSdH0MDvgYWq*WtFcF@;on){y6P`2CJR`cqBo9Xdw-uPxN-htl*)79E>zKUgct zG==Cyb#>BMMTV%2`3SD^c?Sw0dQzs+-d|_0h&VQ1lZGnqvM&TdZum8s=5Dg9+6yRS zsjH8~jdF*Cu8s{Rf1-QTIXyor=|oql8c|o#7&P@LWE1-2Q?gM@XHOx&w>0AGAGIxr zm-d+v%~Cp27CR<{2LFPR^*i4i%Nx`pll;ZcOG1yMG)E6Lmzps$&^1w7!`9|_W~K`8 zSjy#Xv!O>wzq|a4CPN>^)1;~~96EPHw`lxEPH_sKjTmA44(1{A=LkJbWwSKyP7 zAcAil%}6a?Pm*hl-yNK}&p{=^bYMN29o2}Hmforau!9tR32r80EX9UkRT<|l@nyklwbcv*FaC7 z;OXDpmTeJTk?8uLsmF=C!sY?XsiTG?<7~INOoUtC;#;kxi@_0Wr^-QhMN+|qoNsoy z#uUK()%YWK&u)8Mpv1>O=J49lH`*5d*#x1^8;o)_W#y=Inw;^>$i#tHC#sVDjUYW5 z8>SJ$E>lyyyR+PNE)sFR@-=xkG)XZaW#y@~&=9r2aXtQH5&%`&c0;V-?5}vG4fg5@|_&#`6#Sf#X$ago0Yh!k1G4mWBh@j zUpJ6SX|tT#-tp~V6=mywo|}K4$Q6exetPg7G&F3{2u=I?=LURotgVjlu8FFafQjJE zn6-&v&avu_E%WglCD49)!Qq6{osj-zHkJc5**M;>IJOXMLYEn)1;SDI*5v$=xfSF8 zxHo5oUZfGZDgA4>(`MW)SuOHfnc}w5^}isw^n1kKiPy;J5_%f;TBnstUGQgO;3n1% z{$MwlVrQlQM>|n}Ww~C}8pWd}(B=}2t*gVPj-Fb3Abjv5Dpa)Sy|gjF2`!D-TnRpD zoIV5*hvNTr-D1AH}*;~PN9#F(83!0Ad%sRYAY-~BncOUHn(5ksg zN*R{J5$wg7lb$2AvgE2xrY+%x(E9@QyG<^(=g8xZD5|j^0nOTi{&@l%nt%xrlFqbn z1Naxe*5H}R8Oj8MeERg^));O3J3w-k9M3s(Y0MrRu~P8AfqksDI%$U%;X-gvVdR2K zqn)MBXlK5L(9KnN3^(BS`!8cQEXZX|Qk&JPgT%oY*ULl(9|87)vXdCkvSb~KicGPI z_S9JVbQS&M6)xyK_N z+{1LmC2N_g;P{Q0NQA$`DW{i<`b1R21NS)j%|f+TzpN*#;QARRqTPc@Gl>PltHj#f zg|<|f#?onGnEz13RzaNyEElOQ0)#-)4k=A!D)HN&EK7j+cwLq6ek zH^Ee@zq93Q#D6H?k$$Un9C~PP?Q6~~ud5yG0br9v zT!_M2p|1bLIKO(j6-DjIBmS`d00-uSH^ z_$j1X!^h(%NUfz$1EwQV{t*SrycE?OZpjA8(@0z8$`L&9!2oerSsQaA7Lo#W{Zh0%Kc`%$HrSan0{i|4?dIpN*tSQ zc62d0gJ7R>N<&zoNvJ$@RI~rr@Ah}3gA@u??4F}YIYDLp;oc*wooe^eMFIpI=Y+`a zP+vF|>V1S(yxc&w8#pO@iUVn_56~h+@Eth`-=_g;F*|zR_KSaVCQU~Eib$+dL)gt) zJWp?2jNhioU#||{W`}Q)8UoTavR!LmJ<20O%O|J!DDk?xacGB!cZAEf5HR*~e8=Df)!tPj=pUge^~nIl47;1}NM#t4vM7 zzn_dSQATXOe7)%-fAp~(Tb3L+=T)3K(D5qg)thyhpXLV;ZhVj{d#J?qj31 z&zjpErXF9%Y}E~%`%kuKj%N=nNm;U;K6m5;Gze?-{);oJ`ctyH_y(O{^^MdcmWdda zT?5MYTiJZrq@83-m<Vt+=-Kb1P03EEX@3RQ2yvc_fFRCDc_fb6sy(%|fW|mzdhiZi zM&hrzfXYn(+xRb*lBmnMNKE9=`2r46eAE_sm+yXjsy8z_>Ms0}(U0{XY~pKnKn`g4 zqpp^yPgsi@sLg$>-?V-l@m*J#CT|6Z{`aMPzbG^~=p>_gYGUiCAkF#X1eq()SE%jL zS?`-1B3nap^oWSLoB=+$7OK-KQE0I)v-{IprBtfFh7peH3n-DIl>HOTOkw$J)nmZn zHUlkinfd4xk~rJYWVE>MPrvd+8SK`g>etj~?#;^rpkLgT#THqFv)nJyp);`Wzndxs%9erxb8Qh>d)==hY zScz0-r!4&sVo|GD3!Bj_D#DtF4&Ds-|PVbx+3eMnj^rlDFjEp^gc7j~k5dGz?J`|!Sc`j70pWucB z4}biU*}fR)`E^VyG`T6U}M}FxT-4 zB|HPFgukO&|JY5z~MfY{U99^oi%R%_X*O(81= zc%SCmw=Ybr7dI`zN)H4W*~s68>?A-gKNs%7{EG_B!VEsn=aD?u1{fa(KLKioCi(5P zUHVaEE`xSwt(4rrEZ|{Onn@-)4#UHIrbh9A0;1pHb@0o_QVcatse#82=i4OBm z4P8jzlD*@*ZD(dj8GazzA^L=g-;@M|GunrY*s(lo{Nz93wyV!RfMt#CP&A)AscrJI55CtIo4fwY-t3Tm9 z1hX=Ei#)9uC&+5#^H-;3SRki>iA;VU;X2rbK{6WHk%1gvW0ALpWNW9LTS7d`oqA1uPZ%*qDzfWiU!z))D%R8$q`)hm0wShryl9uV%u;EHaU-acDUi96$ z0v(#J^Rikkla8~pTxQ?651v4n)ptj+e0V9oQ;JA%uy-oJA zAJOUui)+)bKc5vj^{&iw_hDa$w#W~mQterp! zFa0;@z}gY3@UDytlfu`&G*l3>Aaa%=3XZ-(G@bR2mA^>fm@EcrxaROi{Ibx$`2NQw z5l<+v2l|!q&oQMDkb6JA2FW_P@K**y-0;b&i0c+9OszS!8K?hh%~!X#BzG$-v_iKB z!~nYxhIZHQ)lN^tS{s?UT+(VgbPem(e|{Y=}5qxcom6CXRe`5bMME@Oui z@o$V7y(tsWTdg$At0!^1HY?V`dy4$spW(_Y9a4~&H9rbqwu&*;A0S&i0=>y&*|h|h zu(>*-qD8Q=&U)z>{yy}bfDH!1Y*p?m!2Fl|%Fmp(REJ6!(DbmooM^vPh;4*nl|2updWjR!?&U~ynIjfmyHx^J#kA9djwScYt zdMm{XE^y&K>^(j)5n=}6#|`YE?}O0u0|i#QNte*%g*C%bDB5f(I^s{u+0xC~9e-mX zM1!_Wa9JJ}6h5}?uW!7H+S1*$V31o(?3lEAyvzXVXGV9mr_-|<;_Em=(=HQDZXBlx zu~2E^xx(p=9IsnWSZ>L~^*urjy4sKY+M!QEocD#k&hll`Po$C#Y7*=%i z2}U|&-5z=hj2V2Y>O_(N<}4|NT8i!VbYC~Ucy}6B?cDm8n9qDQd=wVXAAXSdh1ww9 zqW?#*t-AAiHZAtZ&vyJ?ww{^W?ontlrMb6a&*FtmWU7XhsxcttSd)&eoq()&n}( zyBwN2JKpDxKZ4ciGM+`4btQKNvAN+)T1vzdVTb;2o0FjXa;g%a$85Vh1rL&k1@Tvt zmsXH?_aM>m0r%X?|VKs{*0VDw<&WFx(IKk9^OMeI}>k3&#oWxy|!w1bBA8&Jop z)d%_}5Y>M(jbi+2nf3{Pb~@B6RQ*eaPwGJ4JILMeXETj^XM%WlP9b&I4(!!7q(+T3 z++##eJ%=+EQ^obJd})UW9@v985cl>|?w?jQ@Wlo-?4M%Vk)h*hMM0f1J%RS)zz@9# zvTy!?2fdiP{hW46ViXwG!v+3q%A?s96HuAa!mwJIfgj#6>YYx?C7$sJucBDZcJS*w`b-F54Dp!(w&dz5b4K@ z8kNhMkMqucE+s-1iYgu(7Sqe235PKti#5@!xM+d=BNsxi>nd3K#lQOpzI^9y5Keb! z2rM=}jZ4?ik!G&{$J6}JMvpEIpHedwf7EOR1#T>jDvAySE04gjaXP9aXwITp`-5eW z(8QL%@w$MsR9bKPEF#}-4&`30XXwY-{wsEnu+faGP~yx?5ki8V8-l`ylb%FZ3ndpY z`!os0=Qn3xi8lF>S+f|l;+-k|UfGjW*>!%Miu`}#>v59pwR;S{qc+>!I2+!fY2-OF zKospL07v#Z+ZhAr0ywJ{yc+*ha}u#ngV3-Yzj!b+5=bHaJYYs76^pI97))CHu1UJ+ z@}w1IrG5SAnLBF<+1!<7bbH%+YX({f z7Q^nj6a(08C;1wj=%52fs+|mo4vdfi3e;4Yub5~uMhnD~*)tPT7g2MDf0(iK7^J(;9U7&p%y>V#v*KqxRLY6l+CvPan|Kv05f=!YsiIARMt6JN|2-H-2g8P6bKQn0yX!IS{r+@2-h~B-=u_15>D9{Q@XhXQeBw-WTekwllX+og* z_MKkE$!cyV_LrgGWBV*tFp)`>9K(>;h=-4Zu9$z8EdbYF6!WV`&7VS4{;V*Vkd4jL zukDQ4o4mL4hse1&)bJWlc?f! zq=BNT<@_Hu)49UCQ8Yyiq_j)hT@HR0>Qhv%e1|w7-lg%AQYv(;9dG17#K|f}l+NFP zB|Ef-$>1r`*vAx*Z*3=fbkFMbNYP0z$AIW$9^aN~g~Bx)|2+q$pLDx?d4k~Qjcq{j zTs`w<(t$XIV!-laxlj9YGhG%7&bqvi4<#8?;5Hke8whQUh+B)N6_0+G9jt8{yo|9e zk?!R*h`pbTY@^k&%qd~fjXHDCEG>dhR=m|W(@e=>L8)RfZ}I9Ug5?xIAy=vG>|VVT zf1!@}E@YKQlyQDBY&q;X<--MSx;fzI(?JaAb~?q1b@+ItMH2kxzHb7Ii-k z=|_ah%OB=bkm>Y4P^55e9{GlL!Nw)7C5*%UZ+8R^8T~1HLb%T1DCNbqpHKq}QaHpP zS9U!RKI_tv_TN|Ma2K8V(|Q8i^iom+*gEX5!77i9KS1-*_(_1sAn`@9JtRy-JT`gx z0er#0k2Fr$s&n&n?%Wz9O&ZvFOJybz@3M)Fn~KXomOE{1(MG(XufrCKzrQ&_ zu;bl&ge_4AHWwCUxMf>5sWL@2C>RE_w%&X?5tct!2^O0@Sw6Y9CDToNb|VEN^ObLd zhbSnY1J={#212F({xUML`duHaoC&IS!C#&~mtfK#X4|_y!fsEy7FmhhY}F{lsYQee zZMB@vg)`nEe8$QAwaHV4N(BLgSs(U2t@&aFt1{6!!^Zmn5k5`4Yb0EOTh>h6r#hVU zhoIw1U*AtvNW893V}Sk2nVQhQ+uF`@RBC2c_N~qJ6?{-79sZ7t=B=FZ>4EQbcC0Fc zXxeKD-t3z=OmF#m=Sy3%&k`_!@yq7cWxTvz#45R;ymTIgI^3$gkgju_x=Lp!+k-vY`7H@vsDrl{LT0tXm^#)L1xiIJOQn#XVEL(b$VL zpNKym62^&vOA(iD)cn1{pX`X~h!(j}ITs;SI#DP80h&%?TKD`D^_aX7i>k#eu24a1 zhtQb_fDP@Qs>qu19*2vrEU2N1t{y0QhYm^gzY8U&6`n14r5+q9Le!lyTGvp%@cLBr zLpXr$a&5jQ`mQiei`x9|FM54q7A{L~+k6Nuf9@Sfbp9dwC~G?s>(KjSVKG^aq$D58 z8XbV6UVjqaY|_U>e*>zETj26r0{5HcK^t*|j2KY99TOi|4R_a>`cL(u4K2D9=Qrv( zXss;8jq$Ds<;w5VKGH=M7AKmgMdI#izoC(^(rqjbL&Z zOOp}Z7g;sc?N(jE+VhXZR6(ptyffksj#Ort>YGXKw)F>q>5su8c5b1q~hibsJ*SgNR^#45>$Z@j= z`S5A-?c`rDw+juSf>M2c(*#F_t7B{37P)Nro_^tQs5X{XA|`W7YF}}rf@pPw{PDFQ z!LQU+-gNs1>A0lYX8!CZ-=6pSq^*)br;tF8Fg0^rqc{OL$qjpIK3{L0&;iogUK=i# zq87$C67Rbo*gNPF)3NK3k+BgZHNCm$ehLWG*`cygnR5B}b_;*-l`?&C>p_-_i9QGo z$_zXnocq>ZvDrt|#@T0Pcenulz|Fk>$rVAWa_#)gkqEdvjbFw?*I>K*q_oR$qP zpj5zz1%SPnZA+nmQbmeGHxX{kKWt{4D`QkE7~Jle#Vu5Q0;k)M6udWJDx54J=@}nij%XdRWotF;5p&} z(1%Cvd0~yGL5hi3eZCIru5q!wAbHkk8jNMO4tU*6Uuw9DR^(1SRjPIh{_H2a;l>}D z#89TR;v(97S;V|wMK~JtS+h^n2pjZmKF?o}L}DW_Mu4DW!w6za_;TThc)oJ+COV*t z-dc~-9i0bF?ft6@D`|^Aa!F06Yli6djN{=gnK>5@c%uxcLxpC7{~*tgbcWn%&vsKb zDNz=W9@*8`VfmmT1L!37n+Bt0wz%o9Q~Q(fRGPx%bUk8CvA>!fg{%cCHd7+hv77d? zE0#Q4YQU2I%6@!BKW#9*)?V=RrcMus+#8X0LC32)pArc#DW!Ew+jPeE;KVB>B$Wds zkP!)NvbINAI>5dg8!UZwAGIi-!Lt!BY4Lxi<5kafN+J5w9roOSlwYJmOUY3zYJClk z+8k^~%y~qvy(P!1m~Xp{{}iIj9BwnFuRolIB=vrg-YE5A%^0$a{y1GuG1FP5GO(Lm zgpCm44Q%q?Ve|z+i8`yO??-rPWc^KFHBQ4$!>cR~^xyLzWrw5QxwrgpnaJUGx4nnf z>joEY{9l~d^KR?^H`kuj7wArVW;~zVwOggRdS7NA>aWFQ84w_fi2Z0^!^+aEro z4)T3@vdI{tN8WAFK>IYnNgJeJKA%d@uNTrI9<96Tpdwp+JZn#iHQ_g10Ix&X*^^wZ z+#=;=mT0(y_Pxs+IG>sH2Ux<2G_qD2jmIW8gyz+*(S-w&BvFw6I|&A&qpJrS z4e`*xe=clB5mMIXKWql)k~oHFlm09($)1a)YiWB3zt6Fe#Me#jlyYg2G~4n^n0M}m z_XZa&J+M6No^^UjtXkW9t5i2wcW;IoeR*ZPF_>23$&nbXj-c!%u!{sN$6Je;x;kcd z9mwVT54pR>Pl&J z2kA#`nmo0e;19(%f{+xtcf%;Gc6!AHHkC4uk_9UHJ19<+GTath>1C{~@Yph6534yP zpZz79Oxz#KX?)g|T_e&r2gCg%;-f1bGU5F!f3XH+FgjDbms1w{zD2lxEuc;tv}XRQ|Z#6?2YLDE1@`o6rByTP$F?xgXm0oNvQV?`#>CcF@$GJKExFOl+_9a!=i3z;Q2c zKMag{41-+lJWcw^tQ`vW06|9)PXh+H6&XzJq_^J*3>o{e<7|hh z9Ss?{h<F^R!lQP&?lRo@x@9!2%$v-X;WQc5_w_T zs-y>J%~kj3RyOQzU(%ud3+u~FR62xdQ6>97Y9L`p!nDTpmm*s*zaB6ar%bE? zwF*{HsoS&bRQLxi8~ZY~`-Emg-qDiBY8=HoM|^MFZ2qexrkBWXPskEdlYK}-Ca&uq zm;xnC{I_i6j-Dp`C!t`TTSDeGsI_{a)q*(Y9^Sfh(mMm20`H`!?3HWf720lR(rjWG zc+M{OZS~y0B}5VM>^%`Z^%rs!VAs0t2s+H9i%5mylX{IAO_|$emYkB+pWw2JjvC}%`|TgCr<9rF zw|h*dUp|S+Wwo8oA*p`961lWVdKP4cwMaSby~n=G?VL?o9heK3{ooHzENpAt(z)$% zZ@2l{Z#-?HL7pL|8a#4xTZllJvcq)8W*)AF5oYSj_@I@qRiWV9Hv6wm{X4_t1~`&b9M>}t)t4E8#) zpp?*|a8QMl&0PgP&HR<{$PMs#0YERD8(QmfGXA)G%B)@P@lbUDNe;p7T4kZQi{>d^ zCkeh=AeWB?bkukT5UkJ}{xfQe@!3D=b7=-INL2c(khyM7W5}hXk*7|!CJ--q9~SCl z%C>bneE_gHT^OEp*j-saN~tsAcz>Kh1vl|KdPRNtKSD+j#!pg8m%1cqe>RLg_dLR_ zTK06Os2}*3Mr`afO0mCiVc4428}`GDG(6}74br7dOR8U;9vAMDU+L$U`8Gt_k##UX zC$0M68dSa*+^}01K zX&q792-O{d4DB$M?_Ilk{|Xdue}r}Uey(T&va};kyWUFqO?{*r(C?&IWSt1Y5cFY z+2I1Lmt%!exW{bT0NHPv{J3pP(&Y_pUeA`ri^P~fK4OBr3c90=IztwZ0@YVX=n`$kq6I|bXbYev>FGoL7NQ?Z?66=?vazB#06 zX|!bpH4d{<+onG=Q>9V~NzU6O9dDsCIm=x{jx)w=a|o5P4tGvrNhQ%na^AryQ?U`5!iHfO+ZaCB zY+v8&d;PBK_cwg5_vih(p6}=D@hG7AwZ11UzFpUK(_1%}t#8jYyXsH7>QI`ZAtb2i zR5tF6V}6UR2z`zf8h>>y?0el_X75G?_l7LNrJB@w>e`_}J{VK7Iw3n`woVN96WbqL zpx8ftpchR*e;K~GY415UN^5A%JJhpx}UaEDRN`JMg zn0GVB?#a-{M~r>im+&P_daVx5V9F(gDoY_$rwxQ>*uz*iC<@($5U!3+nAb^2hbvyW$KO z=cUNfU;hPT%bT}JR*5QWMqiM3(1Gc`{5$u-%;T>7De9C@Sl{-U| zyjt6}^s(4%8*C=stqJHIHazwy4akc)MQ)1+nEf%y#McXL(Znj)6I^$X@3;H?U8l!% z2y2iZE5S*b(j1Eu?C2-H+l}Jk_{drs5YqD=?rp(Ikc}&ln2Hp~9gyU|pmufvj^bI& zf%RSVDkx&xlojq)eb$IR?l}rg43`>DkM;=Sm3)TY0#OQh z>_$NtY5iGs)k=79SbUgl6k|%nXuHqf11c(Oec2ZhH&TZ}CE$;aFrhB-c%lqcmU8*u zN`XG~CbbunDs*gy2#F%mA6C{=lcAvcfwHC)O zWHl}8-*f!@UGpZ}W*t)AQS##oP&tJqk2YP?!|l3g*rx3%HfjI|Ahc&bges$7G9ChClXSZ6vMegCH3yT}w?ibJ zEFf>gpM@UJy>i;%3AvZVcse;Ew5xv6w7xl*q z+m87cXoa%s>(qUQc#%I6xN&|45~@+?w8F)XM@sAZEvWG%gM$9)B~8$Sg@qy+O}6GS zwwze@(sY2#Q4vFBWx}B>D#Z=G0PdPG4bc)Jc;@j65f4}*u)f=X+Aw+Vc zPO87IxkE!9{+-e9i7u4vZTGmj%0?+KNP8tsdy@$Wh*UV(KoUDykJNN<5Dk#lq| zG`}cN-KJ4j;Ca(pUbL&gOjl#rtPWq~H?Sl* zXo-!ZL0`)^{^^R#&jQH_@<)&N_1U1U?Y|y$s0edO{HdvoG1?#39u=gd$q5+w?mpY& z-6x!iYe(*5zkPZ;PS<*z_%PH`8~^@%Owmy|b02nNs__+HMK36psGh=uzv%!!{TX%7 z&Xwz4={Sm!UF453zU>yj)tU1>kJO}&yoR{S*3GRsc*Pimqsxo+CGeZZa6Ku6WdCNC zUOv;75U+T-#YBqd{KnlqEJl@-%vy?nLZ)QqCenoV)-&QfJ9hsw4%-Iw4$Y~bUPFL$ zRVQr9>G~DkVkd( z8On3re3wq6buoKG@NeOOFaQknsj{)c>ThXNmIz9fRn({3KDWhpr7-^mCKovG4>lTM zukCXA8Q>c2n!2h=57{$v04OW0J{oDXxiV9faf94J-+S*h7;lZPP7}mc8fD3(Y{X!D zI9_>@8Pdklh)lLQL2ips+RD_@nw|A=c01y%Axhu9Wn-ix`2v9=n~%P(kWUfiqEw1> z@NT~+evzI9nT>@vmfe{bc>NoN5rRI_*rehPj<+AzDC2fGMr&ZLKs{1!oRvP%AN7MV z)Y}uPn7`NzmJya(j_*eN{$sT5@73q|jl!cQ8z23au7GJ|Uo!bgfWrEXqLsC{kRCQc zdr^7?XM>U-7!e14aOmeel7;tiw7U{8e~!m}O@2E38!f>gy`=_ku1*E08m?Za3Fn8p zkJX+2aK5W*`^6$7z+N|X;N6f_f!Si7-J;K^{3)_+AxCq!%Xr#?ri=sltpo!6KDJ5t*z++0%y-rdI8U#v@{dqjgB zic(V>T85r=j!X!zJzmwyg3;Pv3M3VsXD>Jmf+R@26?BCJGYZ{%Gk^)sGLFOT1XRpO z2W>uN!6aXARx{~u!YnGv7Plv>DB5CR$PSdAOZ#GDxA#M@WtWST=hTex2*+n$-=hBd znqevL20BCEhRYwFJ?;04QdWL&)AA%4;rWP(Fp)P2Z`K;6tYo^uNY zm)`-mo6M36!96Ovf=BG(pS3$b4Z>ZtSYJ!*LXiFJ<#4SU=yG|#G2ZJT$)9wqsMp`) zWa=?n)qm0grLuOccc|OuP~(9mw9ehN&jhHS>5V`G-i;AD>Wt#WQPIbuGlx(D*t5DG z0Ukxto{eyiEtPw1H^+)GLch?_YU;221xd9@|FbZ-k>({ ztiIqg@XsvbIUWl)crjFT2(rEh1+?Dv2v5{=hgW6z%O9}fj23HCXS|puJ@3#qfZDK6 zc8;Kd7dl&1`=O1TqI)`BK#yNCUhnl6?~{yJ#t8;5P&ymZuOD`piaR2VZHgH8ILPi$ zjGQ~4z#(EzM!X&l0=y%n;*Kr7e_xg7TY987sp(N$J|prYJ>&Ri?n|F6Xn5&1l_bhe z6WcKsu0rrliL(V_GrViUd~x{veZR#(5nAeyj_4>dQ(@@~4=NIRCe7$y#JZhxZWVkM z5{}X$5bh320h{PaKG+72Dy3U`>C<8y^#{j4Bf*C-H&z;YljwDC*g^I5m_zwX!x-zx zLZMF7SE(-Rr&6z31q(Q*-gfJ_8jP%Ej~8P=J&XMs6yX%M@{dF5(bD$~iag2V)te;! za0=nWBw&A)w_sxfH6>W}v~VP6#hZk^BV$gtVWh+$?@b!m;;?cEzs;v*s)eOS4D35?wx?YCp-g<;bsfN<7ai{J?V z;B!9A&#*gcYmsC*ANKN`x2Hl=8e*hg9!z^hHMTKr-FT+&@+cDW;SB8=(oupDAS!V> zFh+H{r@@4+X~!v7q>lq~wTQ0IZor2c4YSg2*Yr!O)4WPt+=~N8_OxwT64!CTm**c!F5l`e>U`h;|LGXe9B=Y_MHMvkXxM@buS zYYHFGDn{?hb=?bQ5}9n&*87ha&Sx(f7ONY4MDB|%*|K?U{rp9{CFui6^!TIJ*cUz;Z z6XZD9J$2H^&-1Os0b~eL zFdjI+i27Tlx3->C;Ew-nOF~I>c!+8YGnuh{c;8rI#O$}!r%IzgWTN&Cym4&1*q}EY zezO4UlZ`a#gzFNxo7P9r{z6hIs1kEbqP7@d-;xP{4>|kU*sgo zY-_upbJc4EYWOu``mJJPnK+~7?LV|F4_3ANBWxwSQPDTesmUT#+cB$YKe^dMS-T=; z-F;c@`ucCu#IOBF1i3pYPX{&^Pnf#Rg3HJ+DX*6Y(Hg-yPdQxpiyd8C+H1`Q^gYKl zXIbPlC9~c|>DR5R6y>mR584i2*U>Gh`9_h+hnP&LE0%KUo|`Q#>=9{}|MZ~~U-xqh zDwXU!>W)nRuvM_M8qP_;vR6yU9dTUbA-rXKj7Fl~aINEKjmQ#pEcyZc#+2$x{Pam? z9Q9TD+VWW3{kyA%mYjV|sE&6F@_=oUutHAnj?Fbf)-$>esQjHmsAj>(DNvX^5JYX`$4>mq34n$%R;Xz7n7Zy`&f z``aCUOK1NK*?y4dGHs%lSUU61$;e&FM3w%FAN@|!3y;E0_TKfwn|JChX(3ioPxpxm zN3cN+E4pU?wVsW4*~vHYco}`kQ*FS2d+I*pThP)k;0ODjp8MZ^1er8MLP<|Z{F`8? z#fXJ7QW@bBuIu*$x~T45%S_-a8Ex<|O?8mC<1=#F@GLi-vLvN*9DnPn_*84rFb$v& zXx4*IImkr+_j&yjRJD;``Pc>9@od{+b~TGlEKzr{CF5Hf z)2*;FlwAi`+QTmY*qnQOEcCkZ^Au-7PSTMhw`uU@1=4tZdI6ExO+*S8Fc2wLNPt& zWxXXJ2v>c)Xd+nib)IiVIPm&f*1l*5eFL>b^gjV(?tg4?O4M&&YRQ4f@%X&`rd|Du`N>Z!^;gYqNTjzpy@>ECVMskP~blbY4b zW!l^O!F%iO6f_Dur3(6(6nTRarDEz{p zk%!;I&wcB^sRsY`8bxC@e&mf5UGMtlxG{fcgQ?8uXwqX~$Z&Fy&T(v83gR`Z#En>o zUlXBS%$Lec?vLJxLVnJUY9|I+fLYwT#|bjt&k=XQQHD@L2J+T#f?E#XH5Bfh++ z!@DpwLCh=1g_Z=>QTcgac-9p3o>IP6n_c@|cW_Q@c#Seu>8~LE^Nza)-zAev?+OJ6 zUZlo<=IID(f@)Tf1+xKuYchftZEGuo!M<(r4o5>wLdvILBkVS9vC2G+bZ%)CS#5$F zjcUYSJfsYW@J_E|AerJPEUC>v9b4$tl{aG4h#ac(dF&W@|DXHmU7^(YFvU6xZbqn$ zdzHI1Q=wjS1*@dp(d?i$T3Vd%`panj*r~LYA6k$}9n!A#XE*W>`A10Gpr@9;w-Xqd z57#W~3ai$iP?o4VGKhKj8A|qtul9P^#-Vy9qDzwcrkn${0h<5okc0uQSE*hHIBtIFTSZrr)=yk3fxAjwl(8@5h9@U@8J=0RUMZ4B!(kB0F40>>KN zE88(^4)z+d9YX{cvuWccdoTTn#}j=Vec+ih4x5@S+)7OL!5Hl(3rK}RJNt~dT3ENG zfHe2fK$j~?@fE$3eA+O>22nZ*RK_nerTBAJM$ltD#Nr*?&Rk|g(X9if!i~xn4W8CZ zuLOe(o88S^7fwSl&IYGI+XbGwIo&okGIpn%psYW|{yRv{)O20*EZpA`=MCtG_9Gt) zm<1&UbPx;!q3lEsFOpeE9pP|60gcUppFMjlEl$5eeqgZ7hGwd&={x}^P5IWZfW zj8#+ijsN(Py%AZ!s{~9XR!6VK$;M!8_>JIbGg@FdrhBk+SCXMlrrVlL(U|5c>B2ZV z%Wcg&fjiDQ<}QfFcc!2+uJMTJx~hwLm%Cdxv{pFpdU)_i*I(Kd^hYkiVibzy;&C#- z{<++<8roq_?BQRK$SP& z*;^$4HKN9$x<#P~tm*s1M<_CM(7&*E zm5F{K^b}6Qs8J2C;k~pV?RASSh;0-9;4*vPMhSK4uU9?HM+){MPiqSIgwH4bg6Wz4 zLc~Xy(k*A+&~{aZj>WdE12zRSmMaN0bjuCG0+Nf=vh?7vt(W>IB#ZaY;$w<9G9dl# zOg+KTzr6a64duqHsdWR?;R-F<&8>aXUmGuq!LPM zlB)yUVpgwW1bF`_y%d-7~8}l9Vp)Q)iN479eY+j z1JpVC*l)vqc#8HXM|gM1yAM?JwfVm@>#O_H70K3Jvh$^KVD0)$d2aZ_DvjW@dbt3` zdAoWtsIIJurwE;8<@~JEW66b|7`?}_kqg+6wj+qx`y^U@gkAJxwA z$8VsD9@0|=oW#IUuc?7&fVNtKTi-}u)SCm67Q{|Ej5SpSKq-Q68<3#&T3fS^w=6~t z<950|w7*q+a4`^~8WbsuJ$c+}R_!_~V8PH8$2^=Sclhy4S`JeX&0x$+S3Y_ z+FTgLXt0-44)y69-g zb_h?Y(SQ~;LZ>I$X-0zH+@vz&4wZknbh#bK=?P^4GVCaaRMhJsPco> zLuX&1$#m1>_`E$!t>`Cl+i4vuDfm})+)O?2{Um$&#bYa~hZi-`S!XjT+&V!`rW=P* zMbh73$gII2qg}`Nqf4jM#N%~s6-`~$fX0d7t@?Vuz@A9b( zcBdfs5c#q|Ga426U*C8;2wICZNNpWke~JSu3e;mzHrSe2mbBpLNh3cBr%LiV}pF`&fFpkvKf0F06oA> zUM=ZI!p?+gy#~BR_qm#Tgm?W_^gkIefz5WeiYE~sV7OW zVNEWma$A0-z`9J#i z0ijquF*H4DAEZ{|>!`9=Hc$xa6W$AwZiU{s}srpn>bu@=;=PTM1l2L-MyO>72I zC9&d0^v0^WyCriS(e;%^adhk2 znl&G`8{Y(#i?er(LV6dPB`{1^SMN>745>xsCSc>K4;IK-QpalfZgiWKJ! z{TroAcCJNQfPvVjBxS$#G2mZx#80xBjl7{V@gw3k~vnN=u*IzaU?o*5Fxa;^Q# zwJo}se|gV`eOEjK+Ibu;o-##;DEUh{864zDlv=vEOpOuW$OvbraCd*3BE_|8CvuNW zGU57yCm*QwMxw0G(~c)p1d7yYZ9AbRF95arg!(%N@B+5Udmp@vNnX$2j1{k@9a5ao z-D$W*nG=6MO&lJ93bQQ%&X`V1!O12SYE4+(mmL01>5Ye(c9u%|R+n=!d=ESlZs^no zYoqMxVsepYbD@PU#7{#d${oUOm;U?-!&d9+qX^Z4l}^nEz^(h_qYE<p6v=GBNz zime_0Qjhhes5wwJENpa}TlYeCdanLBVN0CqLKn`|ikLpLrEyq%rgP=z{I zf9Ui(65H0-pQI<_=a8eac0pD+%46R9$Z@J@7@y<;AL%e=S!p6ya0t@KzEq@RwM=g* zx=T3P<`iA=`CHKTm9Xrg3EhhnqXDpwOk-&$GeN#dnUgoc|A(>=a%>{= zq*?RV8@zp(v;>0}n0qsRsRX-E^E_QDA!vo9{x#&2z4|tq4EN8St^hsbW(Hp|@4l$-<(_kw=wwp)7ni)Cz&O#5tPc>d!j8Cw5i zF2Z|NC0;@ACE>B#zYjJO8+FYtPJH1Ew>VvTpM=>nr>6-2%3Z2#h)ogH8z!zFSNU!G z2*o%PqRfH4M325Qr#U_PpgwWzqKgTj@dNLLRi&&dcRb??vvAo6FFdCJ10A*eD{XSP ztS@G1Mg+fmg~kX_`f#f5koBP?!SSH?=Mlo64Y!J4FNH#;)|h~_^ylScDt*G6quxfu zlHCyttaZ0!>y0Sh<>x3JeuC>%H?90}B2RM&xA|TC&2Qo_jP_=A+ge?jc;EN^nn6b- zgk%2GIsZ$W1+V{Q=+_Hd@QvSLrVkO%EXIX)KQk8d!_wP0=E&r@Nji*-n_Ld`#rD4I zt4}~pS>A{HaQ0?8j*N3_S9KJj38AJ_lAEko@8S#TXZKns+j*YE$GT29F;y2GIzHPk z*-`5)mF%3Uo45${!=bU^CTZd;^5%eFu~m841yuW(rMPj$k(5o@6*kt z<{nwz+?-a;nDw~Al)qOO3s>~t99Jg6h~$%V)y>4#e7?3{x6{T2r8;g-_4Q<962VA~ z;Xkpw4vzhTL)uM%|MS-@v@z$KA5GNHSnjaU%9XVLff3@7zSa7i*YVQGSh9d))^k__a#FI~N5Ft^AWcd=Cjq&UL#)HSk0)2J z5RLrAKxj-xr98Pm=T*Us78V5@-O+^)j@*yQlBy4~B+scU?7@Zt7fK{?WpET5 zyQkzcf~%W#i?=K<)QygOs6))S_$WwvB5wPWzWDd<@yFUohvDpk4BqNBnM3DlzU?48 z!Bxp~V|5HNbWkHfL%scF2V!%GWx3^+-i@i^s=4<`^LkvT6IHX~kFSpNi`+IJNj1DOi* zOvnn;`}rU$`#fy)gqMCSH(6(V(3XL>XJ(65+40=I6 zzXr5L8PTsg>M4k#ck;;1O@{_#_OGFYf2m~mmo)uFA)Nye)vigl3S4!IQhbSA&IE*< z$JirwJ+NR;a}>lshTbdmV)hCGb=ipE5nyMOk4NfQMUR&9Js1J?Vhutuf-Y+U2Y&kN z_?F_Ehu@HjI5X3Y2Q(F`&Yg1JVty;lx?=?V)osP`Jnhtg1LD&2?|*cK&Lf5gBVGrz zp{x(iRtYrm$y+N=uw`GZc7mrqoxYZ~{9;R%evk9{uK`&ITbgkjE5@Mp@*J1&GSuea zs7bZhVdG1dEP+GeeP;GGTPn=SjPv&JzxfTkKV^~b5oTkxKtSoMey+1IonQFb$lbW3 zd=xZ#nX_xusD1n#yW0N4GkjCRQ?|b=$SseJb1LD8He!_egfTXEt7t84qQj#;Wd#rA zl=io`CPU;EM2>7}8X}+&qk=F?fq&@`1HIMx?eJiQRnh)@^maUO`O!!(Y%nbc;QvS9} zuj1FG=?|-u{@gWde9b42k=0{QDUjpF{!j4eWoqo}@a0+Z==*wyiyG;%CNT5mI zx7NgHQ)z{IRa+m{cum=gj49-e=8tYM_{D2~#wL;_V$y@JySYuO-Oq{GV_o0B7U}z? z@z2u=3n)^nvI|PwP5(=1PjMkq>spJ2ZF?fFC-f+V$=RVLenPfrsp}>>gxsECdoIJj zrUV7cl?y;`nyWow&jk`L^i)&^z6#?-e`d0D9Q35lzEY6~p71uNB&PT_;KEG!acOnj z&3weR98NjlS4byNfE`Qaegn4#h!DSlk6SIi=^G2`rO~}u;a#$8{3@EhRFjNU?Saaz zMp74!&LV8)cIB$}l$t(C1`Kx(HDWzUKo+96fm)kpv=m*pXGV#(_`1l3A72{N9`~R{ z_PG8Ndqe2x^5bmCYo1_|u#%48!ju%?!UbXt)w(ia*1i6eOzGp>qc8)<@$o?28C_{$ z{~}=N&Ro`=I#d{Obx3QhB6~UvCBEw<(EN%wj?uWn_`IUNAB1i320{1hgHj)PrTa@Fv&o5kao--dd(znonA0UYt2`c}w zeTRWQnfnJGKxt8n1Rk#^YzxKKy-#3gQo)L(YO-f%thf4#{V>MUcZR0DmK!BMK?k=R zEB40%!oVrQX-_VXzILp2J)Kub3SiXTXf$QT0`TY-q%yD@K7XKoyS_>V`{Z@&LUwtx z@$^F7C(zg{vpmWn@9GoS{=mSGm}FLc2l%zE?g@rjVXuuOwpUW@xtVMY@^r4cV4a!*7b+^b#(` zdv^y8W1tLn5f-+(XF-$J8QsCG!hQ>TJ5`E= zR72KFscsL>l_@IW_BAq^bfX!Hk`7L`?8aJ_IZm3kmEK{GQxZBZSOROF^i5AUS2_Cs zVL1_QLFbcxKFCEJ?~A(c{Px0*kV!SP54q_jkWassbxTH`zHrFKfsdn_9Ubi<7E~R5 z>ZVJ7AlXjx5?#u0GyA<1k9)+ipo+7K#R#ieUX71(Zv zXl4M0hqy%$kzuae{e{KiVyH?Xrm#G71Sn3;%qf)l)$%flAi7-GEJSuQhZ?Tg zJqCO2^%qShb#A~Nbr;b)Y^3q#<)_#o8<+6cnys(!&3KM`Ru@6^XeN2BzQ{N)Owy#R z1pdN;IDZqZx?(@%qC?X(w1Xp*2VUNNkqwsulVLw?MJ)Y1tnfb#*o}m5oI8^1IFg+i2>sIUnCT z58vtP&=s)kDHfI#Bzj_(UCpgg0i;%kb^;~;x(;zXD}XmHaYI*tH*7~!b(^e4+`iY0 zUe1FU2^CyGaD7;yD)G8g?Wa`|g~HA$us7qrsw7pVhFe>PV*N1Fo|~r~KCQc#R-=%R zOoIgr-lycg$nzP~-Us~ZM$9A7N8h%rB-VcW`B(S?7x54fC*tw|?N;PL`aomd=}+0Y z0Fik|D0*5U?>M?a2=AQEPsC(T#5_xt(zty51aIHT$y!MRo1N>^s_=kmAe>@kM!Nj- zb6DVn^d8YY#-F2pyGC!drCfnZNwDIfkeK@gZ9_fMDiG<37hvanI_9k17ic(M{4=RZGQPc9@C2>zFyGO5WaeC_{yAM zD#m~zG_}cenya=axBAH*-#bb*2g+I%HWxtIUs^~SiJkG^1={mM(oU6jo(Zrkk~)|8 z0n9v{XDexRbLbbQ>dHm>P5yz8U~>(Ji|Z0>jX45xa-c)Sjnul3{y1swjkYLV!!)E~ z!_&z!l(HV#XR>p0!Q7#|YIPQI@~blS^AY}y2X=+jVj6P=5_Xft{i{wdTECA=ztufn z^P071%|534WZLSk&a|bXL9Fwe;hhwl6PB6KXp%WLnS`Yo#E7doF(U4#g~BH*Su*A) zl7enU;M+6!ONrKVcr2naNj}1SkQMrgyU2Jb2(X)SQx27_alA~M1`8ge#)J_=l;5<5 zcS_ZS4j3@pji@;&*q*VW@yo1U<*cUycf%QY<;D)8F2_7kTFDQ2RgjUBH#GaVQ@UWO zA%|RiD^*vQuQ^J&Mq-Zot%$;fp`5asrQ_%z4!dPQ(5r^47XCPle5Do_nP6 zG@ub>dcvHscJz;L172sCoUY0a)umIzyJQ!%eAUE`wM8iO-L=b*E8mD;>1!cF;=hxe}Uhzb5KR%k!;D{8sxluo48w`@8)WupqW?6Kd! z`a76auoN#*o1WVnJ2F%vE0FOc2PR7nB^rD*DmLvA%^JpCx$cI%LL=b?dmv3qxbx2N6y+5rL#><^Kgn)^QgjHkDGJKwIDnpMasXatr%*;9W3wxibI{Db( zugLo;bG6bmXXQc$cPriIc&J_T`?Lg5xZ>FxbAO7z?|qws6Xh? zREQN@=`*0YFGD4uf%+&~WvE8$Ij$Fqw4O+Bx4p>5iID~P>~UKgGrK%5JBa)Ef(X;} z|B0Cm>e`NiOSau%TCQ}~o=I6%WEQL}s4@P$;ke9^Q79aZBwl!WJ@{m+_RV_z(YwWY znXEMv(2Nr|8iodqa_v!@l}V!Lnc{nT{cVe65U-0;xobCy;{93M#ej%tdV^4?pRZ(_W7m2srkn4Hd%<%@IsCX1 zQ}Ne=JU|v2a1wT*5Z)@@9jR$VlVpUQ+t$ z3f*>cRLb?giN=_U-+VFh72vVSkQ2wG#d6OaasWX1)p1|S=DF`O zumFO#bAvWDi&-!Sbl-DHlJ5gsP%nGn?4Ng-YGTLGa)U$c#HA7qa3Z?dR$)oCbN=XP zx|jf@*dAJae{6cPV#;OgAC$Pk3LoIR4lUe4*z1SW@K6x^bH680##f4- zOvi7gM#Lng23O~9AX4)3X?s9{LqY9XnS0>=yXkGP2bSy2fvD3`wS0IwhoRU;+U&)? zx4m!!W!3egPY{f+BG&$Z^BU+kZo2VoybefAv6PzjfUck$pMx$n7d-~SfSSk%Y*qyz zKvrfjC11kThC9Zz4rkXD;dj*g%c=15F1ny}mogR|R<&I7 zvEMO_-LiR0mvg9qPun9Hp(UP&Q{(cZGKg9s9s^~#pf(p^iUCnVZO6bq_Qd5Y$9+c( z(H?jcC%gkzT~L@;uCB7I2BT$D4uJ`$0ohM^r{p-zwR?#oct^+kI0s;zsO-ajP z)I5^!I_6zAF7_kQAH!r!@0!Xq($V|l$*`aQ@kZ(<*Sa0>9%;|MoV z1TL+7A$qH;coRd~aN1X4KJ?spL$5jRx!{dn+>f=RwjJ>E5T{etGPyTXGqwk#-mcpN zjFkrWY4noVq3hoAU*^IKq|5$g3Lk)D9?!h;ap!FaNY?*^s>}CJB$)^{CedusuY8az z{da;Ns~$@yLRhigWq}triguatB9eK#SN-KeOCDnbJm7rDl4r|CMy4>+o3@U9p)U>V0-G5{d5dl75aPo$4_04}z zH`mE|6eMcw!?(D zhtS?0Zr1M1u;A;j+vWpiQKmIOr;Aty!y_~UAs*MpQ>{kNy^CxOF-;)~~Q3i4{vC+Y~F$j6DKa=$Girai+bok+j1?_O!X zCw|BPq`wP2*UeaV^5`6$sh5=HptPXSQwI5?jGWP6N_9nOy#|~4horoNZX9{{z={uh zP$;U1;Hq^~T-PUsh_Ma$?w3?rv;udgip$9}z6{;E@?wGX&yuhg^a)QqjBm-aUp|oJ zEJwXRFtwUj{p=BrlZZhJD;brpc@~W2$bB?h`YU?yJ8Dtfd0)+b3yx@MECOk1Ks?r_ z&Iju0IDjs$xKKU=%VZ~2M7}|;>=JopEmS}|nu69D#;@Sin2i2DGPCtd|geEh1dTSP7hZWz1O?MrhW>(7b7zk5WMjZ1oOH8sd?1 z?xcmUam4t*sX1AWG1XW=GO93}*85OT<+@)jiI4}^Ye3&__zqy$ukO7AO<8e>_U%IV zRmo|L;`o&Tl*#y6AIdmEo%moB90Pv@|e|*FSk$%=@&kB>Q%?LlmizWyZ>EH zUqMNEpNjTb&0n^8FWYo`_$t7DWB<+k9H+lw zY^!UO^#@|3{ww}ef0LH@vm1NqHlO&rdf}l(c=ZbKbn4v%dx%7h_+-pJDyx!bsbVvz zf%s%HY~T9a{v5%-+o7UdI?Tk2!i6qohXart)yjM5dTRxNJxZV-q0=02T6r6AZrpwi zeFOg2$pHEYF^#lmpGk{x5{XR44j5qjIGziQE8cbH#k7}w5lgFNLqA!P!4rqM&`Hqx z(Mvi7#xu)2j|5)kB%?Q!eX!s{XNmNBJFX^|Xe`p1gT81nD?U~S8f|v+%>p8&tal|e zm03=h_sE}2IZRWkFrkb!LeAOHf$Ae&(AWYj>-*KlE0A!YeHid)a=<&He-BKFvh+}V zTHHTQ=>Ev)ET!Py$16n*z`4{SCJtZ6y{3YY;l|cm53H}^(rg{7zZ-1fT26f+#^dAQ z58JdA`G;%_ocWKBCbXysyqcvN=P@ZrbLMG6>__e?u^hg80?U^iKKrTVYZCT$#_-_Pua z8W#k%Nsf`kr6&U~0>7jZJuudUh}=SX%B{NTBgtG0j{{SB+6E09Y183&Xo<;zzl~2G z|D7>NwjS2{RGvd$KGG{sBKf6Kmn(}ZG(6wBDZys8kbiKKkEj2M*LZO);ptCXdk#k; zD@lF4PzZgyVxF*bNM1B4Bh0e>zHc5v*IRu?CEsg>GxR?K2`+DcxF0Py$;WA|>PP8& zpVtE*I5}5`by<6}I3I<_ppPf)mO0+X2MuJk*%+EowvKM8P&HXw4*7aF*@^F_GJ?hLNI@ zVd)?`bQw{>AIg*y{Oqdr zjztS^On}d8l~7?a;f)kUYS|g5N4Xv1;HBs1w+q@_f7Oymp!X5DkOvXAa|(O-ZUJWU zmXC?*<)zkg0KulIut7bXSO3L+^Kh}NKc z5R}9j1i;abfd@zPx^g**5#N_v6haIzyj$Y}q*th=e&m=9Xg74t&dZ)sU_ZGql~6$* zvuEo+QzC`#iEAS~&x(I4_dhJ1i$7Bj{Qq4-xu-;O>GJ8ST$0>2DoJ-;-3=+qDz`Md zCn3~yb+_qCVI#S3E|Dc{UKD?SvjfScI$3x`q75{36g@RmzBy-z2~1_K z2r6-^jQxCG*lv_XX^hhv+so`s zbjvYa1-TqN;)ZurYX4_3NimEL8hW#}O|mWTQcC76ddQBaYSI38JX>1e({9+B%K=^I zal_E-a~J1+YX&3pT>FZs-Km_9tF@dnZi69D86FK?)B~Ja&$#hp+6s_^%qdsW9rS&d z^uOJ9aVWIMLAA;qMb%E)KVtQ&Ya1vP0`Cl%7&`=;@&DkiZhgEUxv{CeQf#T8UYBt( z{%GHkP`X)q@HirHi|A0~{VjiBvHr&kyrygY?xx3;GB3`$IqjXuivmK^%@e>)^L5;L z8aE&EE-cv8Rh9dS=(=29#uADVY}tp9^?){y{#4`Fk@}%q;wmm}Q#5@6RwJY<23Z$| zg~Jd6lSu)~_CNc^HL+vX&cvYwkie0*hUIOt(Gn%shk@FqEuyXHP>`Jp*3%o8&G~#R z0{h^U#u4nr@JDtc_Q%+m7Uy9~_QO0+x0yrKd_-ey0bD2iDj#jo$BZ#>_nZ z=X(Hx8U}Da_~)KWTM|Ls@#yn|V=m#v)LHC3Q}-WORcRct-eRT{c5v4IWz!%m;$9bv z8q=^nqZNF?)-j30ps^V15RTq4gebR^&mH9t-4neM`zu^n^=sJSeOU6+E*+WK1VZe4 zQ4OpU?LON0AkH`PF4vxaz=RPTfJm(VGQVCGy`UppMVT?pLaKPx^3_hs1uhU5Mx)b_`V=%fD7i6T?!R z3Dj6cxoDzff49q-8^tk_Ei@*-`wE(#Vz+ur_BaWHYt%QI^VV>Q<8ZO&sr=DrkB!y^ zwIe$N;Gd4!vH4-kv038jzaPOqS2@VQ1g(Zh0^@po$Ca-CT;wpTszHcfdO!{RC>kD5 zF`h>rID!U^eOjV>?#zVJgT-~m(GMx$8;o;X%5Fc3i8i@Pdv~Y#zJftUZ2?|B8TUlH zWOq6N%uo3i=%o{|&NkY5+p zT+K3BtjUK=NnMkU+w#ZgZ~lx9wB@hFC0|H<@`0f9nrU-juwlOx(O$AQTV8sq<^OsEZC?I7MBF&h(7YPAWFqId-H)H0MLwk;0MGtmfmRGDa` zH?yA~66ZfO0w+UQdtl*w(S2)$bw0)+jg}h?)DeF9(ljJ(s}o9! zn(Y8=E#gn^8gTN0RKIK)Q*8c65jZh%G!CsTIB#7u15f8j5jxmUrY?JVd#U%>a_@M^ zYB1GPRJ#_*7Ichq-!;+Zma5ekF9*`SKG-0M*t8>_k2?HVOC78GuqS-@1^|*kQkC!MbMZ4vN5oKp-H~TgsLm#YKP{`M=%wr3ZC!`*&1Mh* z{17z>BkhPg%HAFS`}+2Xu0km~M)0Aa<8RYc=ybu0V}!fkEi zo~)?!mf?K9f0=f=$9OFw@l#RJ=$(;a_@6_LNlg(+h;5?hHK9h|6?Tx%_OF;EZ|paC zU{V%|A16LJC;E7;QDQ$(_ZIC;gv8fttWLR!w?^WvINk<_m_Lq1%!^U2Du~NZm6@{3 z!&&@V)!{4O*!s*}s$=jO6aV-6(Wxs8Ld-FlQr)lVq26(%cI;(ly%D{s@`#ke{bQnR zVrFP#2=845k?S=1Ep+cRj-klifLTF}o z8{Brf@#=~J~@*qu0pY1LUMN>2UW!#26*3ZwQEg)+`*_(mp{F&hydqG9q zSM30kxmz2?^@F3UdAMpCBWOcJP8zx!;BO z8fmE#wUY|$erIq5;Y2D5l; zJ_muNy!-?M9LG_W(^#iD+Ra%Z@^K@-ye8z|X>~%#Cf*K*Go>@=I15AoFLe zJJY9au@rnYue5o~dAo64MJ-=H8o!1dt7!~=)q1L)kxKjPw76ZdIOMBV@JN9A!P<7dzjytt|)GRh=5W9A%tDV$_^ zWz;oJx-1<&JwTVpm!-HQ=)mwDlVSx91J>2^{hBZ)gX`bu!787}m^8MNBF`;eQB2+- zah`E^(vAkEH&;$$|Ec(HEO1{k_NqKa-unrnSL!N`5v=-=*C|8xJ$jvmz0-{aw&Q%Q zR4-8t8MJ2HR>oB9`>uZ+i4)e~THY5s`C1uNb>1q-qTtj$2EQhP^O^WqM~9_i%6Rjk z;WUePSf(PAoGAfWoQgrd7>4q4{+yXf=FcN6>DEGeS~@q{KJ-6EF9uc}N4=T+deY%^ zg6Bk>0o3JJOqUVWsNZ7V>D1VHPNE2?!-x=*`Q7RWmtlP>Our;#X1nuK(OuX*i!o~h z-aUu=KZIv)BHg3SXglb_!z6mVIA4-wL=I|Z---#RAfz>KTIhi(&m&1I7 zB){$s6~H-4#cKvD|4 znJ!%ZN3BCIxp2Rq)R~PT9gQxb zXoQYOuZhf;r+0-|%c+^c5X=K0XgozdZ^&J&DK_+-^a4KZ05dPz@Ix_LY(6Z}OujU8 zue%gk82T?0Siy@(6@5}@IKITZDyG_g04^&c)o1V2^B3zp8s~#xk`z36CV;fK?%@>b zQ03xD44lFRD%b4YBmjLwk>u=}kJ=ZiO4QD@>-*)45O}InAN<|F)nm) z*SEi}>%Ju)o{7BP?5-DpmSc}av`QNXmi89LGUL)!F@|%hiY+@TZTSgyi%&`{*$x*J zILxT)A2AbBkv4sN6nLfep5!S>%Ltw3+^k=(L!-tx|0tH42Trhgp2&y7%pNx7_UoEgY0i4;_6?2TJ-&gG`qK_`r#yS+QQJ*Z^|dDMH@!2^Rl zF949({9&>Z+HEmiyKmFVMUC4Cf#hb4L%P5?&HK|@&kAXhZm#^K<2Q`v5c&s?MT=4x( z7Sz&nbIASTiH5>mgE-@i9_y{Q47dF%RtmGmS3lWuS`{+o8-CsU6(r$@wT^7m!3DAed@X>8-gJ&cwgfj`;XJQqCgMR zAd4~E=J_7c1#23;*z_Y8f7U`k-1AdRah9WM;ePCsibGBB78|VlH1BF3&O6yi<<^F_ zUd4Ywo&d2WV+porm&8kXq5g1F+O^1FZLA=555z~ktE+$-2rszws z7Ih_czP?pj0zfawyicL2jmW^T^OQy?a5m%%W#O@uzLmbB0vg7#=xAC>!-%Ig2=Qlb z`edBeUAJBJ{InMoNptYiC*4V|sNKn4nQ+l)&}mvwl5QL{f8FD}FpO`aZdrJLY-F40 zXf}L!UK}Z9fEOsm>w{G>`ktaa+Wd|D2Tl5Y{2~6dI<|Y>K?C4S2r(j-yqBJ_W8-W1 zGT3u5l~r`0F)J=2YCU?vDKb!pX~lmfNwOlSo4GpZu%WgqUr|_B6UW>pHEN_rz~1^F zEmI(T|MkKXJk+2Eg;5US=4ehCW%bC&K?j`RNW(S^9ywwqV&+ ztXF)tCiRgNCYI3dM>xsz1%^*^sqn_};m^LEX{!)t;m-y;#(Z@+@k_~C!|S&i3&iJl zO~hm6nb7}C8sm3He5Te{{#3p@7?bq;S}X36qKl8yzNs$LHbbn>M4`4(ZFlbaxC!DG z{ndz?HG1r!w&3SHyR|cvW{JUYisJdECA1%}oLUhQ=$aW~!>iBrmjCzg*zW6;D_rhPW2aEaSnr>;dY`LdkptB6S8W!oYxC%}Yv3*w^wT>IWBZD=}40u4?H2^PtsYz?DsbQi>6E+)dNn%T(Q>#P^B|9Hn90o>hXn(1 z(AQ|Q#T)qPb?|_`m@8uywV$8MJ>R-diQpKT!R<*$dK`))jy*W(pk$)I{C?4}m$sip z9tRYzTMKh-wj(%rbKmCKsN<2Dv{8)u zT$==tM`gwyqQfP4>}od<@yWGt+LEB`Qiz0is*1-+)c};E#=Y zQ>h@|wim$UuV@HIP(fDHg>7I09^1UIji6uVC-XN)suZcHQfz6@!sp`?e6=D)+u4fe z>&R+1{WWN}y=l|6lrM>{OAZ97>^{a75OJV)a2vLN^+_5m>YdOa)+8@8LSjeTJ-9g>IJz&YBt$2u&E_ax?K0_qGF0&Unl zwUQp?8gSJ)%?(QV%QV?UJ{-jVLDY0N@42($pCISNY9M+HIe$3v#?^#~u}+mi)O6mR z(GYuQuCaPkPbICHl@LoRx10~(khDR7_9R#R*75!x4uo_~|0k02rS6#BGkjr7M5!P( zsn(^x!fX7?Lj+x6`2(>HiBXOD>0ePiM!DawZ8V@M_=p_YHR$Ifp{@V~M8JJ-{%h6Y zENd+qX&E_9QWM81;KjXlwbx++{hYQ^-NhF4mbquO+Ou`bTq7V8xn(9MIs(j*wu<)4u%tcS z-RGS1Ed}s-z9ReQ>L3b5iSZr03Q|jLMd4XPeT0-Svd~%uv{*(9AztFNiHOR8i|7WW zdy~Dj^a2vUyacS*?6AT2#{S{v@+l-`I@8v?^~ZLLGvkJoTJtYGh_y%mKU<;w3307e zpV8s4D%wx=?@>|dY{ARNf|VMt1F+BX&WOKJLZ!R1szN`vyE>A%rr+-@oErGrX6d71 z?crOOJ*Jj?_f8-Lkbt%wpH`aXN*<}U=2wO-$f>~lQ}bsG+mhIm)FK$tET2Sn?3N+TIr@8O ziLe@GQOWOFyk)k>>XX-``hK$?AwAk8yKXILSy&L7=Q2EU?*IQk|Ib)T>|GkV_)K@2 z{(5kAPWkcn@DCq(5bUlxMs5_AUk>WK4x8u@n&F_REWw+Z(FKJ55nSC6S_2EQ417FCe7SHsI`mKe##^yy1 zsxyLzz@U2<;Qv@3SF#JJwzpebHn#|kcMy8VVwGHq@hzET;M(EBQQrsjb%=}k`^tj> z^I+tLZ>ZzxN-}0cqA{wTn-eUm*cpNv5T3<DWj>dqaFBMSGMNV^hZ&~i3sL`8RyC(RRpXpe>s66uELRrbaLE@8xZp0o zm{VeFJ=|s%f`4SJC0rBN);@H5V#bj>5K7gvc99?BYiIMW3ta^j7tnuksg5?w%*Pa9 zQ2LDy8pH3!ww<2DY8O3fO;TEn#(_w5n^Rt<-#dLR*$UHm!Po!&esHB9*)v$DA61J} z!<9iXvsd&w=0L!7zXW4ox*~I=zRY$$XFYf7jMooG^O49?4Y&eQmMysq2Dcc70`4o3& zs9{gHVPF;+6Z>G66t_A_Zv7$RiV|r#(_X}~R+tM_UNTzHm^1)-F09?ty>a_F-pa#) z&)bD!R6C$W@nRA4xmfzeLCmrD(10lO{5+F?!!M37T)Px&J}sU<*Qn8YvD-^Y<_R^~ z4YW=d`+vH+^7yD!gcx?Amj(?eQ!hLl9JSqY*o8l8z_7wg?};9~31Kf?CivW1BOyE9 zEZ*qqiC4Ugbl-g>YXQH?L^i=~6@6HFh|hZ$(}scMb+39&YvI zNc5?U?Ji`)&RS_&zT5jI?x?jv*@>IpQwxShmGog$`kMX2R;weKmn#$uTZBx#FyOoR@CPsoGO3 zIes%1@cWH{y|1!26}YpGmYyU?=0UrWf*)z?e;&kmo$j0f09?XYwYgjeN3-7AE=9l~ z_#(?DHWMA;Cpe8;w;6PDG{=hGeI1k4GH&`e*7>$oTP&FSrS#<%V+`g;_8(DY^(2Atb zI*t^?5@Gyx=nrA4K{b?ZMdtg3hhDY7XK$djHP~1rDv*5lJ!b@S`(Qe?L-ingR+gT& zxbs-?LC-XZiLX$8xt_JOjwUJUZc6sAe`JGv(sOMt=Oz${y4~cz9!$t0tHUtjkyep)?db7{L})z;^{hy|%PB}Ew5DYn{n zWHD22M|WZx4GMq=jiF1QOzK=*F$DO%1BYq0A!++gu;=&2Foy~BIXJuT!*L|}mV-&*auYS5-dP?4V0 zsHzL@G83g&65sDE5uXsHav%N|I-w@5iy@O_2G48r&W-Weq#SI^-q;s;d#7ckr}w7J zxiR6^m{+45(du&sr;v27_keO^{^(7ZHg8^)nXK1XdtsQ7f&rL{_QXq0bD&GiD}(4& zQ?s%I7u~j%q2;N*3v7oza4ybPO?obZFRWn?z`EG1VntxT!k%f8HK;JV8p6q=L5&S4 zCmfw2Bl1qPn)T82#%1_WZ;TQI8bn!M_J1Zuc6)d%seSzZ5{Z;Hwm}ma_Q@dSY+AsG zGsmX;oV^wfeALAYn$K{LE7~2?+oY<-CWPc$#XaFG6bW#W*-4 z{}DY;e>k;Hf)OcmQsWxdaTLe4lNZ9r9*nm%^WRaI9Xa}0|4!qp8HKRt8^>Uczc)nm z1g5RzsEcpLV#bYC$vs4Ez2b5nl_INd<19oh8*w%%9{uKHSwR90mu~f&jS2$gHcZSI zKAiriIkj~+@;y{nHpGAQIk7-v)9}HxKsW)|W;2h9O!F|D>^=;A6jMsH zfLP=S$BmVX{?d8{0M9P)z>fg48%6!TglxN4{mn-rBX(yb-)JB+9wo1z@p($%SyxbB zwhr$bOJE|$-w?`aKBi>9P%aw3;_S6P{Ldp^T6m*6RSUC5ozd)UUZmPv^w{Fm`IBCg zS!FKTQ5^$6_@4*=iSwtCgw&POx_e_tdbA-tReF<$6aG8g*e;IBw#^raltB86$Cac$ zZ7+v2L!(fMTpdLIdiY|+1f8vqY(AJ?sK~KrmNtv6je{7pkFlT47d=nZq%a&P8#P+n zp;~9Zzb>bqj5JDbpF<6&SwNft9K_#)ce;`}wlSo?PHYp)#UOpxZc{8c1Id=JnH@)6 zOlQE$WFOpR_Z-p6LDI+1O%7$Cv`|?tmEui%bNJ$TPU5Sr#Y8zVX?eKK`W8pClyi>x z4w{`-NgV>PHLpirY$TC0^3+#R?|io5i*Jt|KZoFF^{$pZ+$}h=y}H&QB8}aSa4v2E z8-~9O0`iCiA_GE}te>*6uNv-YF%rJ!w5S-n&*`Ux-;+qz56*!&g{Ng zc!2u|XX83VZhhWR&fn64>l=RFr?%&>0qUg*^m#YJIM#oBG)ASucfZG>X{T4!?pt0% zWGUi_d&_A=9iv6F2gpX@Rj2R8%*w4#({|h?i_N)}@8-`eQ)@^c7CTkQtpGc}ImgEh zZ(zExuD^$4Ca%>F{Sd?hw`3*W4cnJRSm6`q7$>pO&z&^^y0n#>$#D2c#XWE3uJQx+ zPs;+6Aj1XZcySN35+C;PZb3m+TMUpd)(dEzGkb=e$G_k6WGPkj*U@tCM$0Qk>u8hq41nXV z4hO>iE?2r*!!h*DrF^b=jT!47f|@@X<1L_oFS9D1MeY9hWf8($Id4T?f_-_?vJP1I zpL-t_wo}&pufU?OR-ruSx5JYQdG<{Z{>q=Xow`O?$lkS&!lprfGI3z3vwR`4cj;a95cmH{pBX(O1Uza6Q+oUMqzAOnUj~Lhv0L%bL78$Q4YejO0#qB=+w<<16igIALh*UcSmdw(ueA1(HO4H449GCDh4`OX~0&5Pb` zf>GQ&ykdLf#{Bl3YLpNnIU)}ID0$sL>M~60e%P>X&-WG3L;pW3m3YMwVOBEsl)VKC z#X(V(V4BBEnrJ&*Ap28FVI=NglwaVs(9@q512At3dE12CC5g*qFjG>!VsbP{NKu({ zs%c4{C1R!~&4aMxaHVOTxnEDRT0qIB^$64R?ULESyW__qLRy@zL=}YJ<{eR z6i#PZuFo4hhO;fuxoH}8ZdL%@!uWh|9bh|i{+;m=YX7oyX@^=`>o6y57H%Yssye$m zg%j6)aEZn@-~AeemR6;T&f79cHCL?B2GRYefn(BD3#1*aOl5lW&uvPv1P06PA8S`v zdzxfNeEqg=yiyfYV%Mmn0bqHoR-4!?j{_XtEfUjfQNN`t3I3O8@7)m~c0J1kHgs-j zpzd=-4ePDBA@k*dfj?H&Mk3pHVGg_vhDTZdVa@8D3*3tzS6k=AwjgA029f|9@8JaN&LDN5%lZ z$}-;wVG`LOF863j|Ibx0x~eBpQg`$7%AAWat61o*U;^82r#|Y6VuMDvD&_rApqu^* zgeG|&;Xo|+5WKbk^8;)qVrEVt&>REL#b|0-ViN4>{KQ1es6#3F2^7c?(rkL4*zXhk z)j{E?LrZnV&6#6IEch&tyeZS%F>LKS`8ekPa%>p?g0JG%O*fW7-@oh{(sR2~kcfDp z{7-f}YkzFY&(kDcZEOo5hl*S@wU{^|IYTIT)Dq>uH%FW*!9IbcAYuHD2>{kOqJ3hS zqPAhg2P4<-6ja4R@DDLAyoz24sS|f+PG-7X!QQAJ6^6pZV5=E+4Q;m*BDO~mOC z>c5d@TklDQe~kDuJ%WwmVtH1$J4o!Wcitt<7Yi~pO9Dfei5%(WLp8K-m|QPtb5Iu- znnuQREGW(9qa;5I-paWFvnJB#S6Po~ZFu{hoaluT02@6}d*f!7Z;upw){jsjACz9yj?3eP6wo03-Db&oRk{{gE7wr81(4M~(c zg9QEpy;T~fBbs)DU3Px$ERxXE4$W;ay>X2j*7WHKZqmj{7#68$pmk&O>Y zkK9``282}pfUAaDUyr<*%<-}qsSC5lUf5e%$`zzAW&U&0(bdCF<|EQ9Fru}7$$b>c z!~}1dTwvaJ@ZB{d=-16G?hZMiM&qVnh}UaY1Og!g+!T^z{~7UqeecpztY**}#BaHN zd*P+~pM-Nv6CcwmUbY|vcTH4z1!zOQ8_yZvU6N^VNnW5pA(hHFu5)PH#C3_@+jsR!?2>8QqGQd+w=DT)<4>5yFbIhg$eYg~qLn5hC4kvBPwEyF4^u84MjzebMIU*|bhQH|{$i@GcRasM8$n8-Br6%NZ5oXyz+#?0GS zz)smNjHMI4jOXUmx|f-2Vw#$&+!+Nq2pR~}qZ3E+6vFx=CZF**g{4_n~uojg?ke4E)f4LZ9?2f&Do5f zG0qJ1#FogcDcMK#E2lFX4*rTPO2^HB$z#QqpC{Gu5)cM6c;gPWTBckZF)rSf)fB8 zWET9qp1JfB`CBQF-GKs;T?-n3*^m+{R1N*6BGx@cIF(7g-kH`ck6hL+ofoDHzojD7 zZ!`?=<;3fEn)!E2ZiYF}cJ7Vjx#E*zC|8c>t0R*Xbl}Gg-si2p2^|tEgNCjR2e)vP ztoPZIQKbnsJA%*(>66VBJ}$B70nQ7%1A#MUU0*-@ha;Dl(!>0ORbAZM3TYcVTg3bH zV>0oa0h#3Rq}vI6IM9V3JWKV^Js1w^K*~MatTGLq zdXIKN1UJ;VaKbAc2fFyn0F+jj?TYMO%gZ_Agi;%1I8Q&{n5OHV( z62Fk1<8PyREb4=a*G%_fh+S`aCw_ZTh2FXI%O z&hFY?afOPK$h6aZ{gQFM#^vsFYR)g0znc_CH=6Sqr9yjth}D=Npg?-!!Z*&Exa51g z9qUX!gQWu9=488SM5Bm|4F)5ssRP!2V;vQ57mt}O>CiZx0W@I2kg)E1Q$!k1n^8=j zYu7e8`g4S+t&i*vMQ>%B!d*W6rxVNj2-dkOe8j4N=6!AE{wbFbKdWKet?vpyMl&EZ zL_O`slTB>?rZIA)Sl!r&(yRbE6O;K-H3(%vJK@@wre3xSZ>MB5zw=cM!KU~gR#hm1xf20mG`!GKW*La)8wbLzW2rgYW$ z>3kc|Wmx#NW!U^JqYl!Pw(5gkb2;8`IrhKUFY&+lM^M+NbhSI-RQLCyc8Wn!l>q*a z+V=LYz6-?nn@xdfuF(59cBGu(dWJXM5#ak_)2dvuO*DC}(0$d5)5i&Qr0mrUYjHe< z%?%UR^5`xqVKZ|9pv)8Kq`v@tIrv{hr|qfWfQlG*bwI_om^c}lZ7w@rI84fL(7k=K zsb$lE$>I}W&F0BRN|jF3F^y$O8K%@yGw62b&(iMC%!6$!CS?N&gXdGwnn9U!wWHbP zZNFB6F32`Qk&kFEc3gZf*sl@o;xS#A^h}rOa5B=Cz(?j+N2<$l&w+^J_GwH&tmO%g zj89YjwRWHhjpr@@$SL~eYBU`N(D`N@Lf-DWs=+BuoIA|vU9F4vZQ>llFh0h4&^@kA zc9ytn5IYpmf6EVib&{6E;3}0$f44gfokNmOYKPG1$KljY@_f4jyz`u@alC6wQHJ1v-`MgjHnpO7vfj|RNB zqtdv)$IgjT+W^wxv)<<@hm#W+5n+Q~_8O7$HD=>GdE(zfn(l6&i5fY3sot58;3#Fo z54Ni+QO-nKO!*u*PWdW+G|o1|_~|bVchf%6%E0*pz=lsr(T(Gec!RMKe>FGI25)i@ z7~98Ydpp4+xu5oNFu#f* zah$TRVBWbeWJrL?R{DI`T{Q_Yi@pye1(h`^A)Rn^euQKJb$|$^idVE}cr&Kp-_w$E z&j85f=Iff{?34&7X4m2{*sS-uasOMc;8xat1^Kokg^FEuu<$NwIKxKe$bqK*1it!> z7+$l!EKj&*BWjY2Xxe_Hg=2&f6AUqOMtDxA!4V)BwNV5dkCeUl-`AvZAo{}H04kWg zvO~)knFn;j8{}r%dwg)m1rN6-5ffItN3G8TrNJY$RPb4pUrrF)PWPIa{S?@Y=CzQSy<1o`` z){lT9E2wUWhI(yuDo2Rus+j)d>@5u9_1atXNhJ5#{P65{-0iGoFgUBZ=~+4*0s`~1 zweazeNKbOYykGku`oVcGyozX0Tj(Yitb5{?ZEW>g(zyMp3qV!-|HfafK_Fx!4g3R$ z{k=;KwBJ_Mp0kC5y2D|4w2yNKFBMJ^4-MLNUWg$)R$~0HQY*Qc0T||bzV;H8Y*Q=# zxou)8Mn609k;Y?oKlcu<{rmVCWz&swwJox4+XN`~DeDD_(jSNaA>Yc+l#IC7o}q8D zZ>YdJY58WHZ+Ol6XiF*`8I1>JS8D#1HPgN`bY#_6astR0W1ROg7LNM-!v)%4mk-V% zpAATU(RkI>F`WEOBNY45$-H?_ycdEobPEX9jP z;QDN`9Zy(r&|Pqil2yfo86Cd$dibt4-}klSsTZt$ab}>G)P)6qje*uvBcl>!T(<4) zOH+0Zmj5NNRKp@L$L*bm#+_s^?agttmJ+7`!m7`xc>iznSjue~;$KeosvwFKSadNO z8^M+>LHGAzUqY8*RW%D7qTTuVof5<{sPICdI?xK&>_C6c51Vsq4dds%liEuCZA|P{ zZ>Ly9qu`=9E)?vmyIq;`N;Xj$bRkQ5$v*-J+%2ifjl294`JQOL*4hX!B7$z^SGxef zOP@f(hnpB0LgX;v5IT>{{rk3e^#OpFfxG06ohy@-RO1&MF2bTzmP^FIYmwZ~NUnE# z14fwY5`sGAS#a4g04XlOflcjRfw;|G4WZ ztXzM-I?l11eynuNepp~*QsLC{%3`3!?Jx1^2epM&xG*3#iA$?I%D@5_7JPgdyeYxtuH}- ztf*8FMr*Gz*^@}4F9yiaSNu&9QYc#+?{+r}s?1gadMgx8Z2jQE&<@zVjQsm=0JwCZ zY)ql5BX4bM(fHC*-Kb>q#Ys^K*k>1Y2p;d9Kf3iazTA(do)-cMKm`%mzz>9-+>Puv ziqBGFG3Hn?B`kc-K`PfY0-Tf)>ZJ&F%)JvW$U8O75VPsb68$QNo9XmMXH?xGQwqgO76j7mfNPk*EnjaWNCXC{LIA z#Cvazim9GW!tQ?xRH6O>g;WbfpUxVvfqW?0f(=G{Tho4)t2Q??@bE7 zJ}^59(HMFyte4}KkxA`T?#9IOs5yf&{w0rC0Cj#%7zycARpF82A~sLu9M8l1X2?iz zcJ|ELfbC)OY6}uisbL$5&K8l6H}D-@^((@==^?UiaF!yDKN#h9XtQ9`ujF|wzPjzGJiV-GOMV&4=IZ;|r`&~{xf+!9 z!~uA{5lu}=TBYo=3pj2Z-*% z*oLnS-N<~O99>8=W4YI8s5K?#ZJ7Tw@gaVPP!$pE0~^G`1dcZW=L zQ3V*hcjaVyhIMPBZrG1HL$!N7ABl4 zd0*C0kQSZ?GGgBBdpK$I&nD)wf5)c_x&B}+O32*O_qj|N?|8yM4mdY1!i)M$WihxN zwUIBFtGOL&`j$L08pDoC;q15edwBlyjf>OP)c2T>x`0A3_ifP9Ba(5ROZTlWS@|1m z_x%wqK=)xtanA;uilu|MFQ*S)_V=>!STDi{IX!6+H#qSvd!4w$wW%Ovb1jKaG&j2v zI0a{P7ccCh{}c0HnO?M)C*kU_*(_TYEK26ws59L7GrWi{RG`KO==V$I|J=yHRTgG{ z4lrUEnSSdAk%gd^g&0$O7PH&+EAA<%t&h4*gqye9!h@q=lO~?4k#2meq&ZY&ff{Y-r@Ro)!m1Fgu#yD=OX}n_xHTf;(8f~y5gh` z|KKxWT_N8~usP)I4LoUW+%46TzBR~QS2{SUc?33Q09Y1+P(4+Gx;HWEA@*4QTd=R= z!^IO9)t8Zxy#L4}1X7CYbLkbjnga&6!*n}pM0jJ?sclJJA?)m(5Gc^RiMCXc^-V3^ zB;RIRZUU>^9ZO^78PY)JO-7iNkGrMrzWiwC3S57a!vj1>son(V(m4o4{`qNrqz24q|eOM!yZi!K~W*@W}}aE+909d0|U}kc^ki| z#NB)UWJuuSl_-q|-mKg@!r@ELYVF}wrZ3shW($MxW2@E1t`Rw1-{$uwaj(riir2{^ zMFdz99*N`nI1c!YkCD-tlJImaV0^)2ROGeVy8Q6k3v#Nb9C3b2v*ke55ocv7k;+oh zGAEBo#VTSmfSF+UhJW&e03T&~_aW}^@NuEqoZk<-*t@$2gcB0J>M*PT;#=db#$Q5m zv$;elffG)hV;eLSo;F|MhMbV~hD_$b)}Z8+h1MnUSvD6%_xW&$B-Y^-8-)^1G7S31 zmKos5N-I!)$ZV}oHH8IkmajXv*M&w`yj8A>$!{1h4m^+QP5 zOOVtWZ-+0hssyH|9Cid^KGA{*X+ZNq`D>?lY6+mc5AHYG)9>k1oReYOC(pL{P@}FP zFJ4z97}d;t$-%N_nZoTEiw*g&P^Gu;-S@ZCisYQ1{V5PfT?kzAGbIyy4Xg?(%S2fn(VCLVaCh#0FlUD{lE!D-Qe67_6l zB|S}yLJV+kP|f4yl6)i~T25Wr5Ih?~Yl|JOKOUhzrY<_A3l6=ZlCJm@52YGYr*QBG zJMag-nWdVyK?idy1Ad^`Tx4g3_UbTT?`>yK0Lz;S{`}a(EO&zGPrUt%yBcxdOWF4> zGq5T1#-U(;(L*t}i1(@7V=sd4e zy!dR-cMk{C|5Dc-XU@aivIyaqYTTpLs($zup)l^^5j<;P)b-KQH9R}|qBz5@T=)R7 zY_hy-V2AU$%NbWEkj+5cKU|A3C2?~bi<7_^+%1^7su>9yM9579pzkzxSm*djEZpn% zW)}upxlorfbF4v2Qd@#A;k2ue7N~OW9Nm;s+4L;!hO&v{?Shn7Qy1Wx+R;~urjaI{ z+I*jG+`b(5XS8)Hj(S#^>jc}a_WF%h_A|hz;hi5J+>mHK#Q5ueh`m>&F%PG@8|P9x z{o)YhN*w9}?<&d=*Sl1C@D$8>0$Q?mtgM?C zacqpWjL1zq}ob*th&fBo4mxHVS)nA9ddN$k)V~3Jc7kE->LZ%{fc3 zCq|oJ?iClH#mCXgIS#;_iI$}|n-;c&dKI)gmjE3(+YqKHHWwLx1*iBEbyWW%2G{mX zxQG4Te(<+g=ebMphSspV^KPfQc9ORqSPe&yo9jF7>rVa!J>rNy(ENPC^kK>t)4qZ0 zvN$TAx5eaWBZPnFjMmir0Jr!UK#=A2(PY~I1dU9pZ^;}Tg}=T11zAddpPjsD^qaE7 zp0>x=wJtM_79Je1m(hYH+lm5BdGqJucDe$N1B&Ba);pYiPniRJD-Z@FY&aZxHwTEZ z+`Ve@9=VYR?_>?4&URp4+3 z76IF}-S88FTQ5m0@F4Ac;?coi%W$N&#ru|7c_~a6PvF)5saxA)I9o1k$dz;-gYPRy zxe=v!!w6CMI&6_hXttcL;dqXI(t%+tm#-~{Y!2c_Pz5E_ORnhsO^H_+uPsb}w1B?O z&8-)Z^cV%Fl#|13jCWDiLi1cdS_7c>@c(1!OdOeh;Q#Lkxl=iEO!tM5#IQ+{Plt4q zTPj7)8Mc`tIZ92(=My=$N}(Jh_pyx}qu9tX=Qf66Y#3%X+t>H^{rwT|%bUV?CPxv_p2^m*HHo zwSVVdfsrTO34h)5j>--7&KK7LmZc93k>s#k|V6?ygu9*}f9e$4J;zu6#F_TNmXk z^MUMk2L){g0cqV7mp=& zX@Xb^w{lIDoMQ}?^Hzd%YSnZw%|=LAY{)h)QNk4aT(Cn+dDbml7)DFqt@>*s3Y{@+ za?rLYEg+p-TW*_|%Ir^qgRi$7eUygtzWoWq^3P|%+1xXW_#DM4%SMO-h^7$u4jyyz zZ}YYc?9rBwUJ|;Gxg`_^eGJknb!7fiILH$oXNV`JODa9M`Qp5?eBF3+ zNa%-cyf8vYKB%cU1;?!+9%Pu1(URf1Qz>Tk0Uo&^$hmM`{oDqswoaQAKS zOxgkh7>6aI>fUm=Y>n5GVVq63CDE9bN_29Kd6ypu{g9OmHU>K^awvfgCH3@C>A)b`AJ&0&?+M?RjrkIs%js!~R8_`7o ziXLlCYH8%lm>LtlVHN4+5x#DazFbSBfRi=bb5%<1mroQsPrL2nhODpMIiiZ@G}xuj z9iADVaZtjgG@%{5(*qy*sdBMWr-m6HZyuGrcEIzpr=A7aK#dYmslH z@*P)j4Wy1q;R(P0DxmMzPmaz*Qn$Fuz`G}egH^{buYNhZsm1PGbK`JN8}D5jO0Jc3 z%_IHrWW3-n#jtF~^vSi9)Z zbx))3e#dukB!;qC2FCWK>M=6>uF80Awrqa!a#}ZBX*@VO%HuCP5g^2T&-ZmfXJH#N zuWqmjwEt~Ul`{TMX#rmkQjm*Ts*jnWbuC7jmLC8%R$hc<^evmN4@U zXC7BKar9c1dV&oyJ2z}bmEAn>JY9>9$G02gkXNtt^0iS>duKm2f&ZbmpymFvA%yME zvHn@*h(kqygWx5gV=I8L6aX?>@ZwBk5!HHaL{#W035=ilzH%xdu%r&xBHa{(pH=UaIH$Z9W}Ju>)T zA3}Br74*!yrxIf$10FTGA?d!dD-MJKq@hORP8a`+o)9u;Z~FLm;5nXVs28Ng&;+6q z6Dh&IwSklHf4RK0-Hs^MypzJzFP^K%Z1JMZ`FHigP?uL{wVB&eufryR@>)Z1&m)0A z?5#g~IQr-_MEe>N9`JZpjk%u05?-JdFfRwW@md55tA|aD|JIL$8Iq6jRz-~k@O{Se zY}ck%AZ9hEjrn2^_X!vOePa73<)#O12*T^3LKh{NGWIrmXu$M20rJw2^8wwzri$KV zm2LrXt*iB`Lhd^gygW-1l=_BDV7~l3)@=S-Vbx~R{Lz1>^q1!6`CtFA5(Urj#P}2ig-i!n)xjo zb*1{-nn;tlSH!tS67I8~)mN%*z(<3W`m=x2ps)8c1E`5{(=l_>P*v72bVJs(bRs&; zioL1F#v9a`&3cptp81oSJw0^kux7Z2NfHY|GpD5uQC3N$dyOBnBUTkh8M}NaOZ(cJ zkg~^Sx9LGkIuZYVn^B&6xGG-vzx#Nw8M3h(^Jlw9kmww?I>NBe}*|SEV z*3WAn?`AqGOvU>-HN!q&DEt_{uo*0;5o_FI|90PJ6n-ZLNi1_X)LEy7`sfly`!sl& zV@}Z5egCpwg~Zr&hcxKAk6-z|P~2>-P;9i~XojQlA?5@{JW2A@*A=t#(S@wL#pD;i z>PkMs5a2@s@V~YJStrR)I!vWSM}L?99%$qPeA4_2mv%@2pT?){;Cot~g)1+jKW5C^ z-%@3H28-ci8)Gz2Q^^&99fn9J=n!5Kywf(%HCg zG|aF}xdP_3hsY9`kCN{Xfr;jStcNLilV)ZF<~sx_W`|%q~opeFgLJaf2dBm0%8&SjxU0Z0{+-_lNBt!auzeS>q4!GVfu0p<_+uQN#hgJx~r>MV!er zpIf>(tqT>6!LLDctSK9XdJ~!s6+utB*K2H&+%|ScVm5R4_GhkvDM#S(Edt-yeX@Gd zE4FbuA;yKq|Ilm(?0M95mKEBjf)atUxZM>oyHE;Io*qVS%a7&od#hyxE(Y3CdVei% zE-z3Ej3+7JSPC2vBl0k^Djd{_Kpmqi(#W^NjAvM!r|c=jFHQ#E%xJT?$#Lgn)eG>Q zB-Z!L@jj|JCKh3%lLAewCpZ+%huPkp{Wi53DZWG5z78njS#-TWhTDi%14_D=fk)m8 zQ1P7m+V#${J4$h3TB+3dZkrymXgXYFH8YY=uPt~f%hIGrzoSdTa?uu2&L3jx8XwJMkJmlNsvs^AaAoI=*%n-jAu}J%-zO_xp?)243{eJ^;l(+Lq zAGCb$xEu=Pz3qGaJ)vtL4>^mo__O@C8c@K{KDlgKPywOdIub1zmc6}sr;~5Qur~hV zQ6iRAQeah^^kZ!2o;k(US*=G6oJ*2c6V@Y8w12$l1T8SuyDgCGRm2r-OCaBz1E@FF z!wOQBfc!(>DZTpH4=u0o062Khw&FrMuX$W zaRr@s`U@05y-S#QsLS@_8M8+^dOu{t$Ez$jn<9a2Qp0fY-Wk>0<4x)jdRsW^E^^3~ zGZTP7V1o3A*`6^f2qe-=9rd5|@V>GSS06#t{&C~h)oetxXP@yt3UlAz9s#h+ zyx1kx;NL$4M%8?+LXMcUof*?vKeVL3QvRMb0FM#;M;-5j4MRA;Hsy2pHX`*c-jZl0 zWr8^_w8qA1&~LW#ukvQCLI!xFZIJkstU?DE+37XbXzUM5+bQ|;4!#MM=avVwWP4-e zYK?uzWusBGXI}=uuN$PkO2KpjuAF`H63zSS$MF7PVI!*eLevONKBw~Y`mM80?@uGu zn#z3^Uf3_Jxibx{kG|v8b8CxQ`&LY8@;2e)-p6zZ1>rZDmbJD%I}uUJ{b|sX99n{! z*f0G~?!)*+CBod?cLvqT_ErQbH-iC;4dB3N#oXE}tM@;VOz^iHY3u1B!qnhDG(_={ zc0G3A1njNoc)IcBn9OGJ{wAoj$IkUkN(%@uKcW4T^qz9)%DlA;D;8%fyXi~?>CaTT z{DPeAHb{S%J=ssd4D=Kv4D|@T%(dTZa#f-RKz1fMiHKkKAGANcG+f+Y<{j|H9`<}AS1ygQFM{xCTwz!y>?5R>7( zAipYTfk8cK3Vyq_YR-9a0IEkoT>6QXeWgDjk)C~;+fXSyejQSq!#Kqndyra_Op9nW zNL3@~r4>U)KFTeI87}Cvv)ADgbeGUavh8T-zk__w_{GMLDYqZHenee8D9y(FN@nu1FzQo}8#1QA;t1D1NiXMf@82(vog;q?Owx$HL2JAv zSD;>tI|4Y#EYB2IB&Ex(kq6z_6sYMv_Bk||EopVBL20RzMJ=o^J{)d`@(=ruHs|;15Kg7EeDy!w$XJx$Dm8F1+D^eeYQ3dLfOr!ppF#XRG)F)kzliOh_+&KqW78( zHI1>c)u6>@4S`o;ikdk|VR%hOJ_>)ekl{Zc4Pa_MzUUn&_|QL|!Z{;+ilZc&oF&U2 z60`?iGpdSs*&I%z3!R5-=a?IM)BJ#6_B}8cE`lR)m>eltc48uk+yT9~>%9FxCO9UPp+8&%c+y34zf&SprgyiESUj3sA>VN1OY`aD5vD%bw|CoYg>u%F(zOEbP zUl_Q^DUIlNk}{e;`K{EN5v%+*Eb3Kh%Av?uuXr*Oa=X?2d3{S8N4G(BVt;9a+hi2v zHOD1-Ps_Mf&fKn|Xz~SR=jBsgY@i?+rW`suEqvU3>Wj9Gu?m%-i@UE6 z5rlaavlKlUn@2pF&7IEkEU(b#Ns_z@`N2wTn$5Ap1&eb?wI@oghzlMyHJ?!tugzUn zvxP(UM>gMaqc(?i=w=1XK?qUCGqTi|vXS&ME+cTXT~L*KXtwd^0(DJGz5Q%{l~?>N zJ#y*6^yds+9UHI(S=4;`2}C)0&t30{I~DY(PgT#)(e#)%>ipYERmKG8yLjO$4;8)O2$iZ; zi)U54IxZ!8ZL(rjT}M0Gv`G_2y)wi17;EL#6&YbGuyLzW&%gdXrD50X9;rgM>_qyT zv24?9Ov?#RR2+dw{6XO@M}i8lnpj1P=+GmGXF;3FFccke?%e2P>@lF|D@AJ%`7Jr{ zfeMzQh<}B6>n%ujCh*>^xYqcxw^D)rb1WtsiQ@YVRK~i9ZjqH{CXG=49 zmJKcT5Ah`KbG~(AmX3GY4b*>ra&_=bO8&d5i_H8wRYz&Bb)Ht`s-#Sib@bKqIj%iv z;_9PRx`9ee6_0)AU6Fm9A^8?P_mKHY7wj}9_YU~UCzkxcO;5oz*AZ__Bep@3kPDI< zW15gX?fX58!i-#{u!a-hU-w$8OopUQG*`kdhu4n#x0<#bRncE6XxdJ=-Y1?mxWA{+ z>~Nr3Xn-Q>VBK}b%h+`9(vl_J zGeYCrQfpluNIzSYZ@Bu2R%!9^t^IEz)^#L?j1RUi8J@#>9a$P z6rcVb0*m{uuT+AGZ}-toSMe-dyS+0IsHfw`JGe6@ar>h1{tBBDvqwMW8DO*Q+6>gI z>6RY*VLdquEk9JS;V4|A!{o^^%q#t&W1<^zX+Hq;7Oix2lKu`RR2f`bGZ*V&DR;$wl;lRnkV6UQUrr0H4|?t zA1oNzv3ejzQKzs8MdCdZ=LzO)*41^(AzK$VS(Mp&UzCJ}Zh#Vss16gEQ@r!6erPfS z70H}bSOEO=C|)4imw7}H~m^?1(Qb;9HT#3%e zp*#;YBp*_MPyG`88;vIF0WpUuy+%YiGeoAO1WMRbDR#{OwT}M=tm})|g0e@H?gllxJEMQdATRg!h^UM z+$e^}C?T@iECDqLBV%h3N$;9(fmfj6-12D;`?XS)tu6j*f!9OLOxZ5E*hjBPvH{jj z7Kd~Pa8&`DBf5f#`qIS-@LTN$zq3xbe@boE3>vr1;Vy&r0>lH5E(F9}OGinjfJr*(B2Z!Gv&+m{};z15Na8?!z}gk@>nG=$Ep=+Q_3az?|C~^=@~78D|OYqJm`-%e*B&=oenfv$(Bz%<{J~ zc3F>KhPj)g^GVaF$q6vHbHRF-*u~ISZo+@R$ zZcEbWIpg(P%TY?N2nNOPDIWFpvIl!l80oJMbO-1Q^%1y&cA{peRZmD;s5j5?N1>75 zwUxoRQ?uek#AuA?(U353gq{AezxgxKT}*}FsYvRH3)%)DLb?i&wdv4V;Hyn>_2$V^8W?f0X# z#osZz=+!wc7OnOABui#<#;SV)l0ClZk`TOHOD0D%&a>V6>;V|}(~)1f2J-^(bR9Pf zJ13d4{Eq`}-UzdUh+ZeVt-g^TEY(GZK-1ZFz$G<`_bFG!P#RnN81#ZGe|$&S6mATM{c0OG)p-o{pwia0$B2ZB#~Gd6*p z#KwzLNZ}qnffaueo+8?Yc82SvBXtO0_LOOIx9OrN=Xg5krjR!Ms9H5zZEFcNIV{qmm(3MKIDt^ntVcxm+v9o#N zzKV=z@B&tpvQO!@Y%7k@Yu(6&(a5wqdKYL;En<~dZX5OHP@3jLXJM-4fGYp)>0_ww zFwZqZ<4#B+4BN$u#8^wAeG**VS+m*H(soA*THF{bY>($KOwsjX3>NYQdf)4*|;M`%HE*8BBW!mSzqk;<%Vf=0cnhm(oA zQ{O|q_7+nxe8bsqO;HIVGe74>l>=n>DOE$pA`C2yE|&4HJIh;&d}y zKPy@_=1nu)m#fLZg^#A|YY^Mp+v=GCAsQ6Jlu@NUvEfy$>ORGB!jr#0otG)cp1T&( z%q2ieHO9tlIS$!rj%qWY#YM(ATwSp+yuZ?W`SO{mSeg-&I{5Iz(^fW&}0JZcA<^hq1XI zJSad)jwLhtnGK7l@U0Apxv1-neO#2PhR>8CAT;jDP)%xHxDp?q{)^)pw0SrltF+3u zYsmAV*>di96P?WE`jS?xnw85n!t4lHiMvrJm;E(33h70j+|zUy788CnWM$-HvjF$X zoQY?71wRh~N2>^0)f-Rz#R$=gE}u;k*BGu(7jS1?ooAeHHd!aQ87^f4IcxYk-P;Ew zv;_M^Gk?|fH+Q59z811)<$E_bR$&mnm*~wf`)p;#t$Diqj|3<@)p(&;u}u>Yh(%c0 z=ExmEEB5Pr?>S>tB)`bhJjXeEU2ejx_`LpJ%hfj(d5*QL;JuH>Z=v30AvhM+E)SSB zjkeY7|4hgBcu(_KIlVr@rH6}=xtc-#SKrUfnNZ8_R()WIy9pVrlVf>m@=;IE#W~%d zLFG*QHa?GCaA=hHk$dhHuq$P)N-E~<^_U6M+pj~uEWpxfppYnXWO`f9XiTEq?_OTX zQqouMW3c$t#H=m)8w>s}v>@g?`R*@5ZN){szU5_)zvO0Ejsp4WOZmVJtxHeuNQ(si zahh`;cInv+jhU0ty0bV%?5$h)dG3VyD-91mS=+GZwn%^yP!AgO$agaBx*DVq7E8*n z$X>nH``Q&Zb{*!Qdlw1VKu{e2R?6y`q-mW;3UOp4U8Jse-wAexDx>W`EE#K7&XS==F0TjPelKbf&R*-j&iy{Olp*QizN2LV ziik#uysxmOc=8lRBH}PsvzkPScx9I=&45eECqn1K)3vS13+F6=yX z!=5b<6K_vU6fc)&#jdAng&mIZE}5NR0>6|Mpea!a)VLzq)g^)yGr1T_LwK6M^Yt{Q z=k2i8YO{uQ&1R*r;Jr-l@Mi}_z6ah=Z;ND=7swag{_7UIwJrkvSQBrfwUtG%4lW?|7ei5$pp!ygK zYBm%Vf9J)9pvzxqh0$%_{E4sgf(VfWl-1B5>km2N9y1iPJeFgL2SsKGfJ_c%JRJps z27$1Ll9n!0HFKFiuUPLXoAm9DAo%6f)Oe464vRtU4lJ4l4x$9R^8V(_t6F|C5qE}B z?7H4ix_+$SGiasDUpMrrP%gyC%cUiHN?fhq02=dk&~-*}8{=m9*A={3ZX|wv@QXps znR*WEvEHau`HjONVOuk@syqUR^6Xyom>8)N5R}5 zq3s7qqpT7Eco#YFbDoRnXAPxXwMnh+SBT7tma9dNzbhT)=Tvy%J#Ws!+T?4CnODjQ zI>?F3v20UvX)!(8oY{(aZH10IMuU9J8RO)wAq+eeiJlxF;}IipeG47Cr{je8(Zx^(ka&vLU!nNp>=2)?`? z$;2(`LiII|k6q+uAyHRYRSkPI5h zNwOTxwh#oHQ{LGqOHv*3ntH{Lx!|z4-&Aw1%7a(J%}U(bE_~Osb!KDn-?=w_*~!#x zLxiO;BGoe;S8Cmp&F?y53&-^-4gqkZA^UZ&I9ch%oH=uCLj$;(mm+D66@xNP7eqWQ zq`+g2mRu-OjB)-1evRw1Nq@yVUa=8Lyz-w2Qyq0+R|L^2g&g(B zONH_4B>P0Ig_LE;l&GZlK@JklYzEp+Llb1d{$(r~)Xh|bE9}4S*~TCJWc7;AVLDjF zc4!y}!C6|VWj7zIyFOu)G;>2QZ=$-d3H!z7kti74Fk59xmgFr<^H@?9ny z9FiiKbLQ&tJuM)?0mL=N32O12IX&e~IveIBY5QkUd}mfoHsFt&bBY-Xh$s4(8vaXp zx(*rhb+SxW^3B|;8$@iu#Qk5f%sM}>G#TNyQRo}**1&&J%OQW`8_@4z99~_$WICqV z+fvReVcn`bd1_Mu?A@4X%XQsX_Ou@p$)0=mF*gNr_tQNS8_hLE_=ZdwX(d1C_UtKe z3~$HGldXjVu>mP@e_6MB>l`t5vp+lIObG7H6)F6@0NCa@6FPY?hPM<1Yu8zSFyfbf zOfhEW5*DG)%U_F!jVH6IjqTi|)!bQ#D)s%`#C(k|z$8w~!s^jej5Ewmx~tAz7_)aN z7v0a%-cUayx8_yELJAg2Ig4PgE@5zD^4?Y7-D?O6yleG$ZcUJ0%?rNM_0gfard*z{ zexQsfNRG%_ep0Q!cvkf#C+2#`hImH346u_E z1o{gMVs}}hZsy1VTE0=6`Oi;U>Z!6yWptfV%3bVAO&1H|vWH8xLytCH@@!JKjMLx7 z7D+kJ#ac(9X}--l54~L8}19}8==soeuuHHmHl6L8IA?eSv!ClxB^b5~nC<)Sy z<$Nx#j1~oIKcLb7pVE7srV!$4QDZuqX&<4K?-wAYdx|XwHbd~1JY;y2SWv|BN#n<& zFOR|#RsKGS+b&NtYw5|u(d=(<!-5lmx11EIhQJ7K4ge7k)VHJ+Et;6zno|Q9Afw)C0?;!ommBSK_F#jUKh0p!w zDW|fQ(w4@VW?nb*2*SH05B31X2L*GYp^OU zxzCWO2bO+K&M>3nWMlo-U7J_$Ds#5Q9(9lf8$0ug;WuPrWtE3ZzHhQA@`H}0an9%< zv;TdCrdP|-$jyIJ$lTQ3K?BFd&h(G7sAc9lZKbx;Zz9P&D{coo@RcAv)bc}D%QI)i z&}*UCpz1UQrMrjFwSD?x{HUnQ57TbYUr4n!z)bdqP(06HrMlzD&T}!hoQ?z?0>8g$ zqM2@vhY<$DUir}Ia$Cb=6b>svN>ugbtbBd{k?n5VtuVolOduYt+0WV^3sLHirJCkE z8Bctd$*oMUCU+`8m6{OKgc?@M*(KXV!cVOMa+QFit$aX~&yD-AM3$Pdq2IcgofA~J zv!=f|9X>qjyf*&1`fcB7Na+j|)t^l}@po6jK4TJe%M)ii3%jj|oq6^_pK^SHXXug` zyJLfJPTU)GcyGvzz>Jl(nrd`qz}{vMGLBvQsAx%k>y=4C;oH2!1W(O#zATM{h|59> z-+;o0=~I36oEJ05Nv*XPSCCgYcEI2O%pQr2LuO&w#8mJt)mXK837M@xvQErd z$|ec#3;y`o;LY(G+2FAVPkbUR717U)D-}qh?&*fyxM9)w z;?m{G)WT$88nZYtPzNEO;AOC3Z#ilyeJ4Emx)@e%+Vt}`B7*)GOX%yv>?6N~uw2%D z1E_iXX%fnh2(0t5gTVYph#?|WcINcQKV7VIAII94vy6s*j6yLjv-VDru3Wts{CI+Z ztCTQe>vuZmP^7*6LoY^*HmEujS&a;$?$@wauQ`Y{-!%kl-3G0A-n){7~T1tcVW`T*nW@dxJV+B*kT;fIA z2I=}Ct0Bmw!b$pX{94eFP1FbX>9yOyl0QwxO*z z){hth`tMXPeWAJ-(z`d(y2-Is&kE$WL-C8ssq)gbYD5@0aKCLlH@E4#CE%+=3X7*x zwS>h-L^7j}|Iif1ijl~e+PppW%@{f}xmN6>oO`TI4Je1=y`lhlqR^;go&Sp*Imd}( zQHkub-{hU22`+7@t1tHK^oT1s#MU3&Q7iS8-1oV{viOFQ<9|w7e=UaA7p02NX^^#k8c}>^~^-BSz5HZK2alOiL4Sip|!wAdT9D89-E4duFg9M zp7$kKI;zet!j&{Xwsmvy%*{8k%w{X5M?CU{uZe2kMJ;q-Y{frC;^6U1W__e@GgV$Q z*F#0d9dNWHo+cTPD(QVt*ArBwQ>#fM0n;|F`8GCa z6nq5x^Yg8H!%#;u_ZAACuia{#q4Sa`3;S#K2NP6+4$#MUG%Rm6@-9G_9sUN^mFfE< zC2S8ug(`aVBBaHvn+)vMzY%#wbB zx;Ad!sGNy`1MnnTDh^a*v|YFsz+??hXWZDH`4K8&UFR+zECaSS)_8?WB+URJ%Pj&q zd63>U6vxYQ|_5I!G|VQ_+tb zNL9mm}+l+s&0n%G2w-PA;ViavT#u^Y<s`eWvedueoURr8BN7lbK6jouaSJ!+#4nJ1S%yEGI^x>YGPHtEDY{{yrq} zsv1ubN)H$#9WYg@bFW}twQS9h!M#tiV%QG01;kFcQ*Nt;25^tirupa0jXS! zu}jK7zFMNOI?}gR7FsfbY&8`ED7^VuI|n$0hj6(bwd}MJz6zyaGtY~g&Sc|iF_U5&~9Gy-9TN&v+t1K5#zeGKP z{59&Y@fdgsTb+1o1#ZEcEjzz;I>oecgbXJKB^d7sC{4JxBmKRP@t5cqSnMNB^2-51-i8M;(E6gh<&O^Dz^WKh0g$BX zmO7zZnDSfipHlv76*g1{Hs`c5EWey*-Yt(q+b0Po0oE>$cQl@HQRL|? zI>``sGF{mgf0utSJE**5q=jMOs1J?*+|}rMN}K5Ni|W5p+g#suoAuD~xay!9cLFzu z@WdM-6SmJzm^Io+d7)#u!ZC_UA|Fvv_EATx0Cn` z1w3BJjiov(k3gIemy9+I(h;xBGlMhr{s~vE!_9=jk5sEuTz@njRSlE|HTXJx0w>_G z+MZ!)*}S^E3Q+j0@3~kx{wYooIlO9Vxdo9Fo{fkbd0x|iBnL5-g5x9z17sgQoGM3yNKJatNUM7>eNcuMZbS~0PT@NW1YOFz2%r?V;bpx_XZ-ZN1z zq{DWouQ`Vd3rx>$<4d;tc{U&$LvsC$O$bv}p~O$Q&C@ENphDPXHUYa9KAvt?8;ItO zT1SM=40I-C>(vsC9amAB{6I6{ZjFjhtrkiKlxq|*yD9F-2)WyTU7h@iWkzMqg zOnDTL>vhb7_(8&1W$KnkpX{iEP227<+8T8%ZXs^_Ja{Dh)5$Suwq~PZ8`0cNRnaZ5 z*kPve9g;NiCuHF9{SLj3K(%@*ia2Vgd(g2?a@ja$osq8J^js}`a- zIbPKTda!!vXLQWv^wPbp1+2QZKh(QZzdmU~>57FUx7MwrV86D;Tb4A<>4|n{-iBhV z;^qhL$RcW+Rw@rxy5G{PvUe>QTwM1{Bn@upq3j2Sq*U7sw%n}4jlO-r!3e&{;QUB} z%MtBb%+CAXrK2~V+23%!&|%9o{lLHHG}Li|Q{gDb;n(Tac3%sgVRrkKCgRGp;qq+z z^{tky{-CYXB!4bUR+$Tm!&q(`iNjB^uGy?!vG1huM62ddewmT$P^kNCdQ z1{(rPWT@7`Geelh6+rb8Du#0eS!H#!I=>I8q|%j~A9nhBPi-g%>t`yO9Cas5_2(#t(<8zsGUD3&3gD>UT||?WuGw4a;pg&s8&!m>KiZMOO9VU^iJ zMmKK5GJ7tA+9w99#G+bNnXQ^Pd*lK}y84vv6G_feLY)Bb@6p|+kJ|Tw2oOEg8@+Xr zBE|BbxxvkkVThl$=?2<)&-9*07d<1Wb@Wzg4lNgc$tqeq`Fz=)$GD#MfulCh;BFny z%vP-h^=r~$$zl(ymaeh_kHufxxAw4;kN=aM`Bn$WBaDJ0WyW$t;}R(!bgf?pga84P z+I#t~?OXO!3kc7mZ=4U1qz=!h@$Xw%MqRb4Yv*C)e274LZ68+L7TpWOt)pV(Hl9nO z2vg~L+)M05M_pPsD~}5@N^SW(s0DY%T1Rv}J}|1piX{gr(o|Q5VfusSdHU;>=PYz8 zn+ZiPuuQQ@#oo=oTDM9jGHiu4Yi`Ob3esVjB_GA)gspH-rUIb$N#Vt40t?bCnUPOb zqnV}4&+wjR28C>%j}^fm4ZopTSz5Rz9?#T^?g~56QR0lIe8$Nj=bLoCdf@I~({HN@ zcA=OXdb964yk?JS(mv#UEia?TS~?>2c;c`AF(Mqa`0;_LcsGOup?g&y-nB4t!@*3w zYo?nMntsuAr0pE?BI1ZGGimP=3tdX_NlW(>M1$ycPr*^(0k6E(TCmn=U3J2!aCJPg z`x#%y+*hUr7lGM}4x7x`!AVG6K8+JGg>%nfujcM4-q=nUbww2)=kVh~cwwJy*B4&` zbxq_>G)?z4?wMy~$syt%zCG2$z~P>ja$bNR-=g|#jiTcYn>UQd)#ge!1Y|lt66>-4 zg!hak=lf|;;-dr=O?CtIv4!iLwO3`YBi-3B=adgqtl=!k)Y`t+Emm!>PM)!`qZvIU zjDM&F-*T|)!+CGoFLhEGYVp>Z{T=~LOwBC$B6r~bvvUCH8$79r>juQEEID)tdK_eBHsA zZf7GEdAT+-sWy^$t!B8BzG%-e#d~vvF{H5YEX=z{A_W@sjK@VuZw=i z_=hYQ$i+tayq@cQZW2ZDFKHST-H0*PM@M^ao;fGpFkYAq`qHsEjUk+ER!^Sl?mBCU9IZ1b*gLaO@$5u+nQ324O*sT z`wb6<^)^AHme{*FY)DfFa0##kJ|!LS-OeLhAk9g%AA3;eD2YD6;t8qjp2qGuqT~}-2T%#CZ+^J-=~4Nci70Ta}pmw)deWO z#U4HqohHi;C>IR3+tdU!&FqsU3Ep0cTg*mVPEN@I@`kiD;rKkJg&fjC2U3o4Y|!s+iC4vH27OI;GiN5gHWkPV|bj14-e znIGAa?gReUUse0eQY@`O&fmg@!n((5d>fg*!M(qn#k;2f_a~c2JqgBRa*?qj9;Em4 zy}^8GrJ>*T!mV9qE~YgS6;L_at^0UcfL+dksFKiHKZy)QTI$mle}j{i{Dtl7bo)w1P1$Cc^K;gAB;-PgQI}fC4VwlFz(cLp?DQbH4Nf6%%&SOj;Dz77F zK|`M=qC)9ZJsRsJTw=`WV@?Y*=}N>Q8js2tKn6*a4J0zvRIs1)cSfmC{k(45=Nj%w zkwj(@-83RR@iQ{WFme0z!tNe%-b1sm643hJW zOgqu}WD-OfmNls5=m{{)PfETV-NeurrAwUHvrECco4wDpwruf%KI4*{mgwF zy<>|mP(q{gXHJ=$=?&?h$_i<iDq4WFkLMyHzyH9nvWv~uJd1p-fi{2heZ8d{*R>T8BaUwwC(7z z=S|z`IAt<@2V3r<&-ZcD62Y{alwrY)wj$ z>{GhW>)Znv!Vu-4EB$Q+A`Hw`AG_$`zTBAKR1F9``N%xpMNXL2=spO*oi!UxCfsVV z$)*hBB6SDJ+>NLd#~v13W+N+|2~^#vS5fTmo)AbfTck8HIq;eSDeAWg@M}7}(R zOg{eqcL+u33RaJd0?)#jVt>jT>lIPYPf-0rhpZu$4MT+L%)6LGaF)Pwhi zKTq+YDQeh9JO(0#*iT$9+(xv)0TzdVL=oJ#JShcCi`y&2FtHMSlnIftYZe?rZjD&3 z5v)<80d+!uO;&K7l1+SyS$s8otX^J8w=;U;x`gTh^{cN?U&*c+ZuTwGlqQ|` z)_eylaag4D9s0xGg&3T^g;cfDS7osCtTxN+vlOr=xp`+vj(Mi1G0!Nb#Bj)B0BE3a z9%7xj87DZc91zw(^?*BvLS{2!HG^KHH8@h`#D-siWbsHv>JD^(c;qjjt1b=joi4_T zEQyRY#9$o-GG?4en}+T~Zf5oDEUDGitiqto%vvsFaoI9ZTfqBP+(+2FI?KlSlRa4o`7mn2xCyz~<{a>Df9#lDgY0-X=8USmBA2O2pNsV@~PcL(YOd{eO|8 zO7Wt~Js_>Y^h>rySa1;}S0VEG&QS%Q_;Odx{yR=R5<@+j390uatlgCConb?DzPYo; z#wmhRL6WnLg*%vLH!cc$#b4mevLa{8@xO}5@t0*)kEB*^zfqnNt67jzxo$L)9JaR8 zd*1A(oox)%X2|JtzqGCB`!-~?PQ5bv)}OS*-2WnvlD48?$8JpkwTAqI4A6=c!cA59 z#4cr}6-A(K0(Tz4g;jE977LNixObOntDqX|(7-#6P!KITi9T{k z8H$PuS4w7Vp@AG*Xdzrw%N1TdnIk?Ga7UmOI^Hu z+)h6Inb!!*iJ%}~H5vTk%Q>E*_1>EH$u;f`+HSE(Yygq_BVPtrHqL7*JJ+Samzvxg&z$6RgknZg6bRgru@6y$`&9dIF?8`QvhRfnz!Jm9TnlZ2# zp~$!rhCL>D{?C4J8)@Qnft+5@4RlVpR@^vwdjwX3kPP);@MTx(q;>wGEDH9UL49I$J7Ro=>j--rr8@o2yW2vjhuYbsF!E9SNri=*VcCi*3Phx;V8;OA;0X z41RGq*J`Eop|j2JRBn_E=m~$PkHOzJGTA4m5zn}E5>Be7b&Fg&&W)}heKKP2k27=h zZu32A7@H7{Tkh71dlu1`=Q72AlHWK6fEyo!7^R6UA>J2wA|hv5>m_wNs2}eTvHh1tnOsJLZ_I@2{;~W|S(Gu6$hRJra zDL?U5QydrT{GIf_25TY52-qT9(SER!3;5UaSf!`I1m7lTvC*Y@&6tNxeo4XfYmu>m zNP@iO~cDmoOT0x zszaU;bPjv-5Jek2*o!I%sdPEFp@sZ%)Dr{s_Pj`cjxhW>sa*p4w%*RKd91U(ent6i z`oXatP8gw)$L;G7xRcjj=0#AFbX@*a5ye}i8A1oMKh%0rnw^kGn&(m)VSoJa^n?r* zqn`3_s>~Y{CV$Vw@5EjfX=XfJHTLxS#6D+Ugx&wpFwF!JmiCIrfVzjKssAY1tiT9^SMG zSZRFlQg<=?MXtuy+0^rLzpogC$<7HLE9p++(#wfWB!v8$eW8C6#HrXrf_ZqaAe|72 z?s!sbDbk@Y93!7QHK$p>P<>b}7O5nxuS}xBzl6>o&*xR&kM3jlUQw<+ueJ(3`iHzC zf`JE6)kC27DuIVXhHHfo0^szDXIxj-J0QD*`Yjrh?Qk|^PhZo;;ar*%mQ;s_DMaQ- zsZ-Ay$deAG26|^o5l>AhA8`zx=(ej+%|<1L5TYJyH*eG-t`9U@e*Y)X)NV4Od2^{) zXqUK>HlX>~P{aIp%yyuq%p76cR4prt7qC5;F)WML_cx9OHJ@KO55Mqgrkih=iSV?~ zyKv;px=21OE*8TTcSebCWP@k@uiM~jtO%QO1X}M}Qww+*Yb~_iXtzq-KMuvXxUS|C z(B432v?r0*DCHVstF|y9AmQhczXV76_ovfsGOkklgI4lGED=(qBn9Src*>5&$FF9q z7-Hy#W)9}|oQ~ljYRY~~5l${wX}+n8tocCSQSv{o1R&uoi!9bK<5Y_Ey~$aarT&xSp`2KVoforo;DlT+%%kBIm1) z8-zpQ&b~(OA!ibIgV8GI#6j67>UF6I+^*=_GaZWTM7tscLH#8JiD2kUG+BPiE84CUwC#z$U3G_{0kogqTp z_QAhMIl5Lf0({8tA!w@M`{L+b#AH_Nc46b;9_OG~rm=k~Ss6WNa*kZ6p-D zS=3ydlbgcQe*iw%b9wMhvGxX?RX5=n_ITbzFG+7@ywVAG0^hM=@YZu?EvCg)ZewVJ z;(#q49w-XY%ho59Sjc;i8y z23+C6pM=mh%8OvHS}eH^czfkm5lMONsRuYi-*BQIF!t<&Hkc<``!0^0AgR__69YCd zz-L{(%6zHTvWpdS>Qi~L--2(m{JL2IKfId$QRn15_%Xyug(~`Z{Nh*6y1`zK?oxj!78g!}L z{RIQDixDdtb5-lvR_qEvS{J1QAJ#5FWb*&S;|3qoi?3&3^ZDC z@teun#FiFm<<*Cw;OvTR{!mN!<+k!|{uahGdm(A=7nBv5UshjuPzsn{c-5-Q~vibFQ zJbW~NX<0M&VUl;Ct%7KWPv8x%+~x*jO)@HlK1rNe1%*<~-R5K#_7iy}$-m8Wj`6KRNduf0bq`)9Ksu;W@;Ps3L7ny<&JqzRi{*o$gYTKr?5?|;TqK3S%( zK9I#P#_$7b$5Lug)00H7a=1KP6;uQ>L&6BDZx^>>I;N){NR*z6E0wFa8hanF{S0|i zI#o=MF%SC}AIwLVfBCGaXOzuy9y)_ST?UZDDkAE812<@v-R5DGYeF0}TH`eMMR6Ye zYj zcW)Ghr(`I}zAFuV{C!?t?Ebk|Z7M%V^&>qKG!Q%XpdEHj@$~EuVbiIXwx?FD$9a~- zPAD%UoVT@w11W>8N|W}tK5Afgk2#j*4lMucIWuQsMo-11oR}!z5Um+l?`XqswV>hB zGewnVlzuz{%4^NbqkcKN)dG}LV=3C;&S^@lUrKL#Y2~op(!-H0 zwn9XC+t5A*?<#OegZcBEib>VJQx!fgs%vfDumj!TRgF;l_oIRb4qC%t;+K1~S1g2) zd5>Qt@S2BKv+Mbm8JLYf8|PS@7>ZPYixnhc|4CjDF96vAdjRkvFz(aOUeaA0zEYoR ztn|Z#B@-Y>ZMMD`@jnnJe-q3a=RCQ!(E5bO%niTy?2w&=7NxuTNp4FSaa&~h$%)1# zG4o*$hmuc9MjUcmYw@_?HzTGddWG=gI&pJsF8`a+Nw`Hq_xnzyb~FTTk<{OyeCMff z77nJ57znm9&i8TA;ap+REXoIC9HuL+dXIl^S0+c;!5EWOGJP<6@F;YXzba_@k&V9 zi6RE*6D?;2_RXh@V+#9AudRnxy+p^AQ)la3I_+m18rDs|*HaG9g39R?j9BQ9)jF?x z=D1C1`CTRGJ9@U|KxIuJ`@ki7YTMYa;0^7Nw`9SqJGVA8J^8pw26uG|w-8en9C||w zjByKM|1n~iU_yWB#IRX!dm1(yQk@nE_sXBG1EJu5jMP0Y>a&NTm7vbHb(&{|(CY=s z^4O6~mgQ~P7_BY~!mnb4JpJx@;&>BpF)O-k0wh;^xJ$u(c|1}v3{}cr$wO} zbX?}jT^$7}4K@6L&-jVQLqZZS0_P2$(E0J87ajaxzH+~D(&BpkTHU!Zr*NV-g-W1( z^UK8Kl89Je`eZX`fFV!1rN93410y1CR%|`Keszy2jy`W<+abx;YHnkwQbr-~vYZ>2X7b{F&uz`eoGpw<&c-P~(&!WQ! zC80}zk^)QK>9XC+`q@|I$28_JRXVl(e!HXjU-t#5iXSc;ocdesXI)|UG2NP&@^mY>*jm1 z$RS(@sw@ZF*YL{0%YuPwW*$*@!4)J~WB^rAll|1WfEvHs8N8ii#l4L`6?waQW}OA* zjV(%HA=6DHYGLB2FV_OQb*H|EOd~cPCaFCi*R8zDXb_$~oR_Un85?H%h zb!0kN*^nJ|14cmMN$gTWy%hDoFCmu&9#CCU<2CJY5v11>up`CH%-QeN=8+YIm-SAQ zT?^Kg<7%~;TC6qPA-z&IPPXwaJr^?Oj<$;wpE2NdT-q!vZh03VLZasHX(z3k{q{NE z!n$lxcE|ZC_p3b)NM3RaYdH(s-}iZHB())rSVkcXZ9G+!F{4*0C1~gbeUvAWe0$+a z7Fb*UpTVBuM38qEsnsM^E1;EIBBi|K2tRh&Ki?~k;knLsY=OvloOSO$c(hIDmU7u1 z*1hEpdEt*~`qvm8bSo6wwT$>1zI9(&KQ-Sa?ZkFKM$@NzSvRkt0&t5s5O^sVy4g>% z=u}O&R|t=T9$he*8hiiR(yzXe&=fa&CqvWnm`bi%-?`S%x3Dv5)R-2XfmasM4?vrH zSc+5N3Yg}B0E6~eAmF%d%gp)i+odBL7e%W-{ss1 z-vG&gF6vta;{CMJpb<#N-Ju-6as9BxQw95HV;gv`c1o(N$1#oeKD`qUUmH1&@0@7u z(OUhZ2-yjz!a^$NC9Yat&D5|%q5ratdY)WQX&(1hLKFlw z46~4dq#aCEWP7s5-gIXBQAw+UEz@ZtF3CL~51ZYZBG|r4f)=O@CdLxSOtQ2ZF#E5x zb7sDJD2ZH72dp+x1fCADqo`r84$CdiHn0GL~>&b9U6pA^OE0ATe<=<3K%EKmp`3Br#GD0J^ci$YKpb8-Sly89ni~CYn*+7 z=h=|&@IKLN1=b&UoZ{g-q)A|@bA$m{f0(s<#X(x%fPgzRaOKIh>_K#gqbCbopxhecSV z$w#(-@UWhAX9bU#$>-=#Hr&U!-Y43S@`Kn}zC^d=6hRf?mHF6YR?pZ;JU4kcBrYRZ zb9Fkt2{TR)qt>T2p2~2GXYB+ocB~U;uwh!9DhIMS3>ZThXBL!cXH2s6vDb^uRt?m$^-YD1jy*asX z=o-wA@{y*9Wif`6wH$lN!B0&m>PXvBLktz6h0@P|QWmna56)Zerf3HKQAim^_q(#8 zbVl8I1uf>O7g3GUBp}O|W1lQ*jADo7pyS^`!Z1n&v>xBUC7U1jPMrvX)%GWwhy57zE^h!P;NEp zN~Why19wvNpM@_@M&lR19J<1WhtRKj917 zu|v>zm3~LxpijqjiyNLWrqaB4?;w&3x5o5;|L|wYo#%rb)Hi&!{^n%Ge$p8*Oa73xo$}UN30ZyYoR#$kx;`WNZMA?+^ zXZRUpB@9(Lr4!?>d}?`s9|Icy(T}ij(ic5~cqL0HXOOaV3!=F$@Zb~C5bV}8ua)D;tMTYN(j6hBljP@Pd_^MbPAy)NTYtDvdoHAOdV}LrV#5-dM(P<{K ztc(_Rm3p@y1`=(9!-@z2znTgt;ozEf*V&y$O<;ZXwL7g@s$r*2R92Cnb^|Oj^CX}{ z0S~{na@U5eb`DJ8ROi&JAN3%l^PHrqXNt6Q2Nt7^G7*aeBNn*G(jF&=a-^6-cGfY% zNq#3IZ*Y+Q7NIOL)GOQzVP~l1t<*4Wf@zOs7W+3|y|zoGz>O-G4F0qs`bX#$=H zJlmmo#b^A6_-lfr>EhvZeLdto1+napscE7FE3FX~dPt26&^t}^YZc|m>h}9#9p9ok zc5tajSU3rx^tZjS+{85X?^^Cl@_}!S-^kgsq3+cn-J#wl$8CX6?Q{-fw*UyOkc2(y zGnvi9K(oka;WjQNEDfqM(gi{~%B#b)t}hGdz*ZI811!7xJljj-HL`IXyiN1X*_PB5 zHb|XeU3;C#^ahUDWoKytjK0iNvw(%_pJTi-E0@_7SEUuFc7)l8ncyPFvCnT;zir6Z zPNG-^jHt0Ji#SE(lt|2Ky?ii~KN{fp1IYD7Dy-bO&JD{@k-_2sDTmP3O^;H^zH64* zXumaFe74*?<@v2xRpsD1*}duf#%ZgF7hi)FQ<(cQsJy0o3dCO0JzI=V`rUDY@SxDc zar5&QSMR5P!M7nf+hmQKN)4{Ca+9*x&5^YhIR=K%rXR}KxNc9}g;6ii)BkJVMfubla8Nt5C4 z`Ih>I|0MB(rtxw1^+AmQnPYM$tyy79hO6&X8qBA)-Dnde2)fmHg9ZIcd*2fGE-#__ z!W>P)q_=T210u6g$67VBxybVvL@<@_s#kKOdi;^L=z2yAf0wHddYKp9a#@*mjf6y2 zCcCqH|^+ zZCTL~k4BnYMj^-+x%Xn1f;#45z|z|S-r0>TE*DI`VK;7&X&p2EMFKSmak&KM)cRxe z+@!DvjdjDpFh#X#Hdad4i|s-T929T%@=nedZ=;((ttd>_Z(XoKlLuXYL>!6(`4~2- zffL-wrsf4`a{s_ic(@eT)sie6Hv0R$aY=u+b`<3QQxY9F{_4KR%{MjP*A|4U8n1VkmZ41|3l0NvNi*`@(LK1g1fLs3C@0cg*C$DxT z&N^-@qR^F}TZMt~L_3FS5I~2uAcEtX7!*&~jvYJu;+L@TTwbEb{X%6!?s8JoB|?lx zWYR>c#xU%zyTt5Zi{ZgXF!4b$?MGCU9z&b>IX?YsX&ocWGuF|bsKyRFd*#bnmvwi0 zhWO$MdOo2rKFulCf^cV6SdN)AGO3LRn|A^{+=NkM91!z;15+SFyOnrdiRKWl*d;Xu z_BuA>wYTBj`p!Y9T3igXi8==U>koLhCUW}Bt%PlD^Wi&K!jl1ItqCcx6NJVO0X*Z- zn{K;ej4)Ykum{w8ysf}ZwRhJ>BU|GB3is!eyKPDtmI1N+W_su_`DPnm z?(VDQZ0g)$K*o|5BQH3IHyXxF;MqZ3AQ-*d9GWfNZZBbzPm*810eV0jLc|Jj2U4ne zCf!^r{KbHvi~-QnEgQDIS$YOP`qjCYmhT6v$|xMVRgBQ4^ule(h?xI41Jxz)e9f-J zsb8uYQ&BT9HivBoaKU3+?R$@ZHAOJXMv_YcQGr(|MLNuOi(*Q=C|#;xVs!t8HkSOu zV_G(uzFJP}LBOG~WadeRsm@ramR}EhF2BQLV3bw$-AQy>hkS1f(E7~{iZL8ap2&S* zgD-6<4ep10OAEecPt&3&i`pVnGcZj&X17RN5~B?5T8GNSJla}@{25A#pD3Vjo8 zAtMb^Ry78fW0nYv+eHWxV>4&uC3oN?HhB=-AxvE20oM5QjbyC=9^n_aO~UctW>hkL zM_&Ch1wWJlMzUbfLG@CLbJKeIK)HWSzM|M*#9o4Z`u6^3PLtUbLZ}}xF z;sVS+#f_G`xY9V@h}9vGV?JirZ+zFmNWH(2M@D08#XiVFNKlS5wBoPXc^%=}3Ab!Ifm0$oa#u-%Q;VZFX!W@9Rk;!7^TfXxZm@ zAR)D3(?L>KWJ)w!{h#zXphRE;V)Sr=0J_gQ&uz&j;@(V`;9_0pNVkilJ2(dO(mPC& z1x`Z1PVRqHR;gGNCyehI8<_C;AQ<`JGlWPrOy}C zug3|hn0=(5%p~#@Mh2v^xOd;=^-4mY@2NMM+>^>|iASGU>R;Z&l=?pu$=aB_I6(-) zSH>q1>8WPe?yc$)qpb z-W|_3%ICT!=o^LYZV`9OQ^F5y$`a2Px+woGS~CfqAjuLdd)m4uyL3zy04Ms4MtHp3 z4KlvNyE|^dEQS5UAXg=g`CYsefz`IFQIvwC4_U_qnslI4YZOod9hKl1VC%{PvV8&NV= zULyhM-kYC)9@d;4i?v}0Vmsh+-}J)9w4IDBHdQUohCNPRxn7Bg0CdtxFmQ%_hdEi~P4l)ZSDkNd=>i&Q>%XyQB z1DYZ4sX*{a5j90Tp^+|6Ioqdv7@XF0hRPD`!2Txjj-cA30vTHMzC9`2j~%uF&@+n( z2&W5&!|YnS<@txOJZ-08Ja`MrrlcR~d~V04PH<;T9Q@XjJa_-+z5JdpZEk-dTcu^u z8o*u_>MpIHm5DC|nMl*$8z z*Y8=}YXO*W%FiWSJAKx&ZGDX3JeQ?%3b{oxdRi*&?#Oxec5nB6f z{U4|Id7cG(U8cZrwRp%Z;_ zOC8x4Cy=ja0fs}<85Oq&gFD71_V1n!unav^+8pJ4|EnVtsLc}YyMI_KE?V0S9upPXiXNn{Sfdc@>Us3iKPsjb{PQ&zgFxZ_>{!2?ZczN#`aj8~}rF zLEfE&pl==YD%IxCZxxF{yedhce%@{qa`u(c*s|qtsM~ zJGC8+i!qBPy>$$E`we!C?Qr6YZ)yyG&|aDSs~JXULJ+t<(4*w63vgJD2f6#jcCu;y z_2S(Ln;sfyinZC5Ef}tZgtfUD#EJy=bA|VJ03-fP%0$l{U|k( z(dw;K5bIa;t;J7Wki`m41i0I1@cV{P+01fqfj$9smW$S1_;q&a_lE2VgT}4Yd`daH zP_hDazzH49ldqf!`>x0xpK|OH`_lI}f#CUawjy)*=HuyoLE5KDQJF4=vV@5t|9-+AO~?p$fxEQE^Dp<%HaQmU#u%I~Xba>kM9(Or`PS?z#SK+m0r4aVAy& z7cvgM@op@`_tdnu)cOI7xCOH|g_fQK6PYE**1n2DgKF_G0(2)`EZq+nn4FGjL)|={i13D;Xx0z>VfGqz`ys)h)O9RcQ zA1d~XmigzqIa}LmJ;A{~>dTUjI~hh#ugyZ!s*d zlfZ!MtPk4cQ%xabS4sa){mQXLR$gGqaaVoE&vq2Vj?u4<{KLw@3K#_>;4iW(@XiZ` z0%oa+CrR{zO~qAKOt9=OwEtk8Fv1z=Z`R(HvN%bb2MWTUp14mb%IIHSkE%?hHQKBl zq`LFoUYsO=|0)3TOk@NJSRHybPorjfEJmyB-NQ4jv^#2h`)sV;1WcZ2Q`n4~&QFK+ zk!T-XKKUKoA&zu7Bf+`#+N=put1oh*+&KnPI6V*DuKRPU4v98uBfH=mCv-ajRjmH| zGysW#`3!nW-PNz$nYsJ2Ol7AcOzZ1RNtK_)cUPutV8r(ND2ME~m)2fLx%+~LM)uzwc z6hMF*tk&R*tN)FS{tgzQ7jlv)J9y=2&kT$VF@{X(vUpvvy9TAUZNaiP#^AG{uznjI z2;~PY-D*osfj}|QOWAa1N-gh=uhy9LFHV{dGd|$)O*TncSe;lJX+gXEU&3n-_SxIJ z{h}Wz)(4j_TVx7{t<1ZEjaVm|9}jUbI$pq~ON;Jjds2T><5Y5Zo%NBp2*r9df&o9} zv)KV#xw|v~(*LzzeW;e)Dgy{(q*~wJ)n&1gKgq-72P_LE!yaw-^yVoNc&p8fyNJ+u z)RUl7h79d=F#t`uJ7BCeeTiF2yXdsfm`J!mL-UQq8V0~6*O4x#ho!5%zu+n*AoxV zTfCmEBkHZe8xsSbxCgKFM0<^g@1wU`kqM-Rz_`}Ntp~^LKopww?={sfq;=K)N0R=APJz34UIzfd52uID^)BlnT|m9k zvwBDNNWRrDVi_7V(OO)R5Jx(qM#AX>F1XFTKzh1y;~vh@TE~`ZM(kwV`B6yk$+ir9 zR$HmI^&PTVf)@9ZcZs}qnGxwbvG*e*-c&;TMS_$mr0Ure5~94PO}9k>rpYhKPlE2S zQZ0@S&o*8ZR0TioA@2*k&??%5jI8N_p0rwS_W?+T?C;v|mAP|Se(=iHw}Yc6G4h!Y zzEQ^^`Q3CD?*=VZJ3A(&>G(%qy3Ttuh@(P7=7cLlrviGxAK-$u`7&{1^CE0AO60SY z8v6)``4`KNQ)znNXS8#%J6WfEcGoWk7L_*;vc|jJc0bumaDVJia8J`ur<|ysNsr$u zmm3Ze5biT{gK#R&;$3Apyt)t^{i4_mK3e2#S8!pkswKcS-&JU8+Y!67Gb)$mfxh!Z z^8xAm$i+*JHb>w=GuN{ zJ$;X!MlRiA0sH1?erFZAftRTeyYR}L# zkqu;;F$8)1^nESb3OWd~CvhGkD}j}G2Ft9+pzVc%H=UnFN}>BT^G@<&!s5mIdhB*q z8%`)lTAojzWrdBqTJ4enS*jk^wtYApTFM{XdfY_q!9pf{C3sZ?RJ2`pmvL8T6K^D9 z{JjO^PTxm^C@#Vy5@&PQ>j!+BPlpVzMi7jif6(utUC_PoXFHh+lTp;V&3+FpNUEz8 z$~00k#R(ea8dH&<>t|w?MOO?EpQ(YZ&4&MMveft)*UId!zABG~$GNS%W?2xm8=`M_ zY_*06j1g6^#nka~JZjz(1~?segdQU>+sOA^Db5rr&SCOHNAC-)gb_}o(2DwX6ISNC&enYFfWN`w6;vX*I8SI-iz!?k=WWcTK`OJ z1q)W&p)c34^wM@fgM)kwcj?F8+$Ut4)%frx_t5x)LN*IX+vF(vJ_^4KlY@nl$!wQCzl7c*52SyxPN=eWnb7b>j^fI$)ri;^(sB=w}TmX zl;n9yxw`B-&+~~LcUZ^H;~{ol5%Fu%3d_ zMTU<%Q5qo8cjP(S0f3x_{|DR%x%PcvzmgEi5ywf|d1_C& zrbH44(D32$vbqhS0lV2qd(sw7s}cXQbYWR`;j6g;qG*k~OhOBW4cRegd=`zh8<^Y_ z;x1XEXV(fAKV@+aJyf=y-3i-vnv4y_qQvblZpN1$iMmhl`qsOJghEv5Fs_4*<3C+6 zw!{pGtj~ErG%aN^#wTKw;kSNjOO6ggN?Vh3BRKTPb7k--CS|ncXwSHrcFd;u-@r?n zMqFRDWCN96gMn#We1XPOTh5epsL)q2eO2NN;2(#`wANtF#5Nh~<%FhnkkI$Udf8d9Iw)fc_}jE9gRIG=ZF zk=86?lWN%Obz)`ts#doLwy}`XvS8lAno)q+sF4AwO5qt}w087~zrhiqwq);I)qR~HfXuF_e=fEpxdtCb~b z_8#AnCLXIq2E-rRM!BlZ`$E^I9Oifgf}3^VzYlx46MmnwctyL<@VFiCd9x=_duX?w z)n+O1!JWff^IrTnQhLxVW(wf1(Z0qW28SQ)Byd82HZ#{X+mq@FFJ|TH< z9@2rF(7;dWuzuS8NfE(G7boGi!GSR#MB6Ffbmq48^t&#dmQdorKXMwjY7N~tsdIN% z*hd~hwt}t%0mT|M>Dnh0Y_Jy>Spy$JRcVPkY#3%)M`2lB6CjK4U}28{ANZHDN_TL-&f?Iv5R z%2hn|uW^TqN9;jSYZNNaQ>*heV9jl=QhPl_rE`M@ai1`6=e}(-Tec?f$g{vHPCJYL zRQcRdXF&_8m(i#*Y9+ht@7_LZLd@TSRN2j>VEAfJgJx~kGkG)nL0wFb~yJ%e*0rLvz;his`E;aqPpZJs>sUk#0sUcLG+Wpic z^Q473W@+>~{bhb)w%P=`+9twlZ@aJ>>2J-q9oh`}r3)s*y}Osn>7sl~isIq`@1ehH zFYLGuYBuUoe~Iz$kxTM1aCG{dFlWb7wAzm zF`ISg-PDQRh0JO9X*g*Nw954iS61GfB<5eAN#?KFYQ%PwAZY3}eg}!Wqbonr+OC37 z3fb1g`<6^eVd|_jeu~QXdaqjH^z*uuY508JAC^1IN%#VKrIakl=hl#+OG>0O$SxW< z>GAWwD#&Acuq!QFhC3GR_>%$MPM1#ckl{!e=m>XD5M89_&u6EriTrgxMDDeX2Vi}vO=r>zzhu|Vaz0o zs?Uj$L=Tp!r%vA@O7o)DUtgGF@ZJX6d|bUNO+WGMFKn|N%A%C66x4C|IjwauLRII^ zZl#g8_?cLjkq)yb4ciKgH*~akT>9D_vJUQWFM3v3B<<+YTEEpig4=#b+Df-8;m^!j z+v)DH=*ZA4hY&7$KJ4D?fdw zq)7&!8v}=PVS($Xt~;<0c3|yVy#Z`Y+!<8cgC#ArL)gRrnlawCrFNOxD>No2fK2-~ zf5+^>2XRa&1DiehVp~LXdoDR(o_H7Pq$7w$-wYh2)jYt>VqMS!m!Ct zQyaCVjVR!hjnga%v=#Ke7%rP<`gZ6MgvHwEN2}$q)ZDT7N1JJr6UdH&oCv zZzKr)r9q7ZpS2)A-tTtL?CaISz&=f^ZHcAhh zPVHfg)M@4|@aU{RUqyuR{3F&%Qg;9QL578PU*8S*roYOQ-!Gl05pgZ!8_#LNJ2s9e z{4RS~2n;m{&qZ|$W*Z?Lq$gGAuaLagjG0wyg5tm2*!+=T1IVdW`e|woeJcFXa&tbN zDuC-*sTP{x3qP@{uNz0R*F#@4XVagXtpGFDWgV(#2O0+p=P$w5hxT(c%J&p}k=eMP zs60kau!NVilfpjbSKPEK$jT80)>JN6MMD>K5z;$C;2ig@Oq6yf#oGmk5%HZ%s zKL`2;2i-i1?b5D%ADgk{o)`mQaLj#pp@d}>o3{g4OUkM5v&4fOi>eQ*_^I9WVXujD zdnJuY;pRJe(M20{jGQiz`FA$JC%Jy63T^l|-WvPun$c-D*lMW3j|xaS zTE1e&Pu#l74_9xdJTMWJ`URU>byK8YOfdCl)$Zcsk5+Xd6>X$yODB7(S`vBguGuPR z7(MkAp`2@);hD|zw@cR!QZLH>%YEGHaFRNR$4D(b*CknGgpK9}3>Bn7NAu}W{4H|qj%Xd@-44$~1FrKRU2t5i#Fz7<1Uo z2S$uk<#9+I%~H^qKlYekntUa$RcK#8ub;wZmlSM7sLY^TpNNt+(e2F0@CFlp+ovB$ zw0mr5-(ls7Hr-|9zhD{jaNLGyO$cFp_B!0#|-DWr!6vNQ>fFP;-M?W2_ z{H;+T+M`Gc>;Y%b6R26IfV+7jJd@=>zP`{}dag&2JJTRd<_`1zJP{f9)o-7kz0C!q z-Y%Ogv?w2)cCV(C1Q&Nu0><~C9JNQsirvvdDA^iVP1{m?7Ixh`>vt?6lQPQ4e(0 zj<9m+g+)}3ioMDh?`6RF>T@r8@r{D(g?a>_^Ct3x`(cb7{*oFy45u$DY*`~V&C1N? z*RQ{2L|q+%|38+_J)G%2{{If494k5GFsbMur<@Pl$X)7|&P5JG?oz4H%we-R6)LQg zC~QfE9G2uThmFV*ZHmls!`LuvjE!yPx9{)!{rmIJuFtOPeZ4=g*W>wk-tQS~yizvz zffY4cSxtr1_lbwzOTa+W_!((a9OcPKU7D^p|q>|U=R$x?GJkxa8^@gotOu*%*-K@9_n3`KT z>DUpL#7be+rS)(a+_HM~dlXWQ?hSeJV|7b0D+d?)(u>`!Ow<%qD=Fc@^I_jyc5#hl z^y6?b0njUQC(JLhR$QYCmA2a590b3j$59&hIm9{2Ls*`U*%bU2HfG1wLMumyUx}46 zB6apwk=EyHCh+6$W%VbXJ95fo`^0BZ<^95q*Eb2{f+lKaIJd}$X1AHH6F*SUc|r}< zg=YA1`qWvs-fPc^KL@*xZ`LMJLTjB_whN)VP(6Ry2`Cv2SK!5>vdz!21M!QWiQib| zj3pLwc*1{`F@I?C*?GuSoG4A?@<&H7>}4g1CER*6z}U9=(ReZ4cO$sU5m4Idgalrk zsENKJKS*sg;_ta1tmg>1q{Ij4_u%g<0s%;)Se8|Uc^O)Uf81!R-v*?Uojz=X%oB2VfP9i3nw}lY_oXVUQWJa6l(p*1 zv#d3ZL=BG)VCFK`o2`*@X)DhLF_sWs8?WT=R&Z{i8S2 z&Ppi*A*hcJbQ0gk)@0W@lXUIkJ|4?dpxi>u#@ z(L280(;)92cEK&}*`&D`Htr}rd%2oPCk{R3Au6VUneTnDq4?2mGusjXg7^&#Oh{9L zQ}toWBy$&yQe(*O#hpJCPNLi5V|dP0Yz?mgybVKt7UPHF(eQ-JQw`h zgluj9iZ ziJw@js?bO?)Su1)Vlx~SPF8|;?g$!BxaMw< z%_s!oBE z^N60W;P&l#{Zm-CG5}B_SKMMi)z0kp}b0Lj0#ZhvP<{A!wP=nKq$W;-+L&b7fI` zEnchmw~dP|w2*65px>;Lr*&pBYG}Ouv+nfAI zhK}HFMElrB{-lNepeAj&id;PoT1F?bSs#)$wdb}Z70S|&jy)=0B%=}MZAz?0Nv%yi z6nL}YH?ZTG{W_iv3x|FO!V`Rw16_fkYNNiED@`nVB~@mcaL*gFIu+q8{^5~uslx=- zQF7s1;2Boa`&V(9mKNWh7hY53ujV?|Mft}BTYjzT*G!j>SqmQ9+O$v7%Q`%IqLNn* zBdvBUTxj)KYsfV*h{Xz)O@SJpiiu+phug-ZXIIzs9PN9eKH`Nn9LqK1HEi-)$7*?s z-zSjDt68nMv2qXWG}h(ZHx;$GK^dh_7^C`CSqlRav2~*!zf}-lwi>OF`l zK6X_Pp_i)!yS3xodMpt@?M2(jX3I$6O>-oHVy?HJ7eTh~pcGH4KGv zE%K4(b5|1=LX&T74?ZYocbP<79I+?;>wfxeoD%g-S({*!H}8xxy27}jSnV9 z7-N|NHGWsT8E<&!A?&yl9-A6Wp4yuvw`RX+Y`FBw>1EZ3DH4uEq6Q@5V;mdnFfWJrioa z8jr!^Pi@ZifucJMe(tuyNlEDY=Sq%{^k>CKuBz{#J~|y)eLVctJr6(I(&qt9!0Kt0 z1XUBit!Tl!y`bb#b-s#p7-g$02QADPiBk)@bUA-ZLCvT&>p}EsFNH+L)p=U6e;M=y zZBs5`&j4|wC!IE3dpG025k3#H^2W4?*R0cXNk;JRFr7?^7hh>pu>mvI9O;}(m1Cj; z9*D!+zGc$CRcisK6vZbKz4wu^Tj^AI$jvLyA-4D$9tNUxIn*0GU zf2y%^Npf+ZGY+!A`h&gIOH;%Y%bfKpWzGXrPUH5axh!AJSG6Cd*P@ZhqH`A_T)%T_ zXWSEziQ8}wDF@*JIhZi++97%>zp+Zh_@}~g#0FhrqZ`V(zGW^5(^n;s-OliNPw6!b z1r8XjJEBqvlqL{xm@4>;C zZr)bxue;;Jt<5yXpFE>qY?{Nw_T-?$sokrtRA}SPJ8ajMHczOxU3&;(q#%3yg)o;)HMHBfX#qo(IitaRX;sm9&ipuCvGb8I+{ z+kjefgx=(KvEXo|JD7I4Z7Bn~bGysAJNYwZ(~;lE5B-aNt&*e;k>A_?&mp2Q3O7~y z`)*V9LB}caQY#2R@o)w)9kPa#H2261Y*phngJF()HD@IWFUR^x!C)PYt= ze%NeEJ*pkO+eWMbDPPUAePy<4Frj1XJXEp_HLgfx@>zr=s7Y$v4 z!xO18hF?>m)D@!N*RV5)1;kwWWOq+p3+}S4Zg;ETrBCDW1Nzt6_egK=9}Se4AU{o= zP3wB!EWS~PP>FqrwTN-%b6SR!})2^Vc9m$JltJoZWOV9Ca z@A1~cREy56$@OmSGcsHRnl_CXWoy#^)Fi==?V&fdX6b*wT+eNWu-@*AxjKtp5nr${ znrq>PWPW1#iW34S)uI;$f9N%G^nNDdBLEDv0C5*f+%#GdUg1ig(_QOeV!g?VW2}Pk zFFowO?W|*qa4|$FY~p4R1owz-CweVQ*Iw*!lfu*xHPU2o>>Cfu3F~y)p3bng;hVn( zSKWh8M|!?@QV@@pkE?DA=15mOO6;F`8GBFr?4s@%OI!?Z8jHi&T&%y}{GZz1&au%K zaplR~hQbwf0!akMQY_|b(&E8!*>kp61KtSa;CC%`j1Z@NTd#5*tK>E=ee06Bvg^*% z`^mc{&Ot0($I5unmir}KP^<7XJ@dOcE#E)2D>M9{(&Wq2hQAP1!3m#a=i;9CN(&xe zk*ds*_on1=RO|{MI(sY)a)Gqw=y`!_5PdpW78RD!CMU?5*u#&1D!B$$kbp)#9>w*< zw;WE;YY>a`nE4#gtT*j$s$Fkg7^Jf%q3}VZURph6HVO zP9b2AitF8%xSQXs+OI0rxm$mrzEid}y(g;Mf&f<7MLzYYI?ml<)H_HZU-aP6xA`1b z3VZsUne1}2j9gxFUo>is; z)p{AtIqc}wDe6G>y+Q5is4N_ODj01rTHOt-9JiTpjl`JkrKkK}RiO!q&EbVcC%8{A<>U#WVL2)|^&UkFr8V=P zj6hYY%rGkZr%xunCS=UI-g<-xenINR-*o{;ep zFMk83V1OR>XEOLUE$$?>YlUv=!wAKcxYI22e}lP4b@$;E`a2xZo9Dm1xQ>+N-eqY+ zIJxrr$?+aprj)BXtAA8k&qQC?qw(#78YFT3iKtIuO{YV7Loxsd z-1F6Rb@5-Zo$Zm|e9E=Za^{9L@R0!m#S{IUZ}9;b|Jm8iTYoEd(>`qQP4v8dMrL~# z-Cf=H)P48U=*Y3!bcuQmHEV^w0Lj{zAC1(NUn=xtX*X4UA>hFcQ2dgmdl$^dRcPf#BC+>X89YI(sV)A>=1u$jpkTC zi!9>#Rk7@3`~2GM6!Br@`y3VNY**e|C?SLWa*N%sQ3tbGla@z=LG`7hL*fRI<09$TDA^FMz}m@;X*Hbkz%~f zhp4Q%nd_armi@SN-nMm~BPO=cGeexi_?T3zM0t!o(26WZ-#0k1Eo{6*EtVUhOlakK z#wp3F8iuANEM7{gJ-O)eb)FC;32i$KT?1mVFXwHLoy{-icf(hb$Lv9xgaXo8A)M}E^;2)hXZTFk!BHEl{8u6CTUSkGo&F{*h#t}!? zzy3S)M3o=`0URLN0e4?E;~=5$Snr| zt?3OG$nS)|T(N9G>im-ZjCsOv2LYwI_@+JL81aaM#uDlYJFpc7Qj&U9Z}yQx^aMB> zHgY~jGPIE?5|_9OROXn1wOv&9fe!PJv>eidp`a?>b2Dm+ps`Kz*=WwyPi-TmEwP~m zH`4Q;1_&G8+mzx2X0?lIw7>hUU%l7&kyx+930+;u5og9r9I$_1*!sU4+|g?LZ9bPv z6AAN%!CgFMgvF$*Ymp5T_)E`FekO!92W2&9b*gh}5EzG`K5H+dsu1u(lYuC}FqOD% z?b0v&F`z4UC`_mXD1XeHM2Fr|K&#K&n6GKh=9-TiZh%~1wWQWiTfKVcE2(O5Onn~oPwq~KQeEel7{2X&;`{JLc4 zS>FyRYxbkHNd|22=QuZZe1m+>key(lQ1g2N^6`=M5))VbI>kWy>zh9Y-4Kq})Fzff zOAh-L{L~Uj{G}+)Fp^R&`86a`_FSATy&7%F1oK}^TP2}e4vi} z@(-E%9V19Jqc7vPo6}C++H4{&H6DHc+DX(ZXJEq(`ObBs6-PtLkbzSVfd})zo{kqoS=>s{{#%7q+}N9{TVTH7YypJD-B4@rq`_b?p6!PTe@+8qj~dXuGBC+5TDEd zx0(juo8+}@4B0cEu^X*rs~)>8dbl`(3r6@H!qHb_NYiG|!CQ3=SF7oQ4<}B|e|Wjl zI1b4aL=mS99NmF7lv}q~N+9Fc95c`zlro0jnc+i{gc9>cQyu@x@xC5tj$6fd$MFI= z^Oy`!53-SRwk2%|W!&M||9*4z&bZ94h?=VcoCxL?EIlD%?bYu(a(B{ng}zq#E9-w6 zW4Me!^v)w>xlIkm;n7zw9F4K&2rxer*v~?|Hf(%#t^@~_Ru=zuI<8f}5q*~Aybx~p zF6a%Tmb3ydAgctFv7I_sAz?R*HN#Y-?xds@K_kg%aU%;LJ)9FoL+KmJS=0A8gZl)5 zdZdB6`Hr@TY*u{;1zty82W5N2WPMWXNtyU#D5V9zja}aCG!#Wi&*vLeAgoBv@IKcD z!r8)t({z@6cP1#II@Kqi0&r0XZVUB|-ZtqU)O;rUxEhoXM=?ibZxLR*qKP9qL$$2D zdp7LRdlc(L(eRCCqZ@jZdwmc~r?ZEriq5gO2=fU|i7%}0+&cKY#-Vs~%`5_BE zzMEV4S}g3gJN>js2UWH4X6E#-^s~;y4J=Re zdS_urcatw=N43Vewh`W+BLiXo@FFhHcqOd=lFRNRIlHp+PWlNavf@D0A?oHJF7fDK{l{%4?=N0&zLauQ)SQfI)s;^LEmls z#lCNK_9UA-DlN0cHzxejuuk_bJw>=#=y2J9&dSh}Dt5|!S$jHtySI&8wn158_oD#Wh^L%7Ycp6zEI27X0TAQBR)O8wtj_dJqR9IxJR!6I&;dTXuch8T3CDWe zGZF;6|HxTsBsi~pi&Jw-6d%X^-AK5;=1^jLhzcV>7}{`im+xbKoE=T^R6W-ylzk9U z;w`BCk{k{SV70+l0_yh&u90zq6%&z(;gh&(&loI15sBH6l?aYF?x=woY2Qfl@Ndgk z${LNf%w!Q!RfkIxk&yEAaJe<+DFebclEoQ;#_&rE2sPjc%O$#_QW{$e2;%HO##xm9@WKj!c5y%85&zJ_>`O_~X6w$aSR09V z;en~aKxe`lYLeZc)}$ev4{P|rUf+Gq;Sr?zbHqEU$p&h>v`l(}z3O5+{S49AY8XcA zX;g9!?o8f18d&Zb_JRVVi4HksvFqXzuRT1m4~sQOJlGqVMP64P-R)SbRU150{CW68 z=ts%C1htKBoOpxP-6_rFy5~{9ggS~S(QY<3$G{?HekD}yy#G-Nwwb0ZxRUvI6WN8= zowIuy-hP$5uFsZ4=*BXo@y>|oLdzsGKlA!6X36W#y@>LHU1;=O+HEWk-=?ADu?3lQL!mo(UdaU3)-Axz$aXYLv}|m*yaV1A zdB7l5_}G!(Ui&lQ@gAMCQ*cZK$?7=C$0MGaK-a7E%_x5TCWGp%-0bvEiS2tWc0#Hg zcA@^Ob;8{^!>`FUFnmz5y&g(lz%AzzV+vJq(%*8-^d6_#uh3>fK@Z1O zX$3Q62zeZOdI)tM*M7);QChEryUgX0qN*(YdPkD069BQLOad+!)j|icW|;m};rjzv z{e&yyif5)r^R{=+`@N`kZH4WKO_&U@!9PT+xwi4b-=C&V@^^cE{iyxbyZOr21bF|+ zs06$DU-N!ZfC#aC=DlhR(n^7bOc&TLlhGW#w*OouVrOPbLQ_^U~!w3a#ek z`?m(ztsa@mYo0RFA=|CqY`uZB>3s^iU5=egL-B-N>z1yc_Em7QlFlnE=SGbRd6qK< zZk6nr;nH4tC9?5K**L@woS2+;P*M`Vh!bTW=>SY27sE|bU;Q~%aVIcT%Q35~mO1*k zfJ72Pkoir2Z`!CY8CF|R^L&@nVzY{J1hIw}Ugu)!g(&?=6X*H}AmJaUk)b%IuO}gP zh<@p{e_H2-XeQrw_&aSn3?OV8*#*JmFU%=7ZH78 z>|x=js9)0EEa2ku{Ev%KRl>ykOnHkton~W{J%<2K!jHBI-?@^P@CWImKwY3if~L>S znL`GA6J$)DWfHzUKpXuuqPLTPB~v?H5&$9NS5-<|0l)=IGDIfIBO8j$Q3Xxa@S=m_m?q`z^Te^d60E1=F>P@(oo3 z5-~!1X47KjYl>uSqCv{2{R88_(0gd2N5}H2-P!w?h-Ly-iHy1cC3jq*k}SsmsBd=7 zHM4~=k!RvBdX%TQsOv6SeLPkFhZoP$Qtb#s8!G^e(NLCL1gg~dAt5((;=u;|S06iB zVO{72vZPV3MAki6ZLsRRujK20iJ`I*_aAv2sv4Ea3XfFm|DBw$oiD|+`rz7&h10OU z475{bA+|46NFe_NFD~x6dO`R9gVsQi?9a=t{Z}NI+c$R__`fn)TO`bv?TSOJ-hP=h z@Xg)%=%@2XaiKJNyVG>lw$ZoMGkNbwFI%OqniSH^t^%7_@vu*2=ZhWi=12GgSPy7s z(YF_#q0)dizvY0cjifo~>Vy~HUHyD-Y!5|!ZT{Z}<+B{u>3lX4r;JjJi@R<++YF&h zi9sWPa_a;R%Qg&{==_MivfaPMbp4{WCYJ?6ZJh6gN6m)O>be1d2?) z1e&pX&w0TRx9p_trVb9jO-!r#05W?EyvD%_g)e93UVzLiTp~~U2#vGbMUC^6zbPcO z4w+Wk-UJKEDFeYUOIeW#k)dZ-V0ky2JI#8F($|*eoUv+L+N2~?Z-XqxJSK1Z*)HE$ zzB_=v(ZqLptU)!L(0GBxZC$MjY^*)oyeco9{UALcm>W9AxYa%>|eln5kS# zqLsh`r8SaQ!dw6WJCyYCp4Ff$T%;%>ex4j}yACPwoeL8dm|gC-agbsie_fk#GE5WL zeWK~ihOn?`dRxIaH+4+gw!(eG6Pg>J)sKrGM57G&tSHx`e|anG?@|Cy$L-gJ{j3Yk z*w~$bM1e#b%4m5TsC! zOy759%?fVX(l{*j3OU-T6E;66#GREoQ*X&sty>Z9o3zgda61ecWlO;+uJ%?&JGf7! z6P52Sl%mRmqv@7;A9x=cm*Xf1)jDyr&Y zz|JHeAT2~(?g27rPM=HS9^u(MBLT4%3~uEiAVIP**>)*{r~lsQvIx(M=YZrtSDBqy z^Vy!;RCQMA>|98Tys$8nle2PqGpHC4A*`UhEZDZb`#xuOL1e1Neg}Q5wU)&Ups`gZ zooP190spWsN$0N@b=LR+9O~QS)}SUHE8$9!n>@4DKIGwvtC0hsFh};-DO1u?57FI*?05@vlr`Cm63+N9 zPE``fVUNF7RG3Fhe!W46VpZGqE48L-OzrD0Kg88=Bez*1|7h||O~Odi#40HL8Dhom z#--=_8{c$38KdM_GFG70_xFKrxbBIeU~;kBh*6yBaXKcvTL@wIiU`+siW=S9Z4~au ze2X7o?Txs`!oJS>d0UV5^<+W!u1OU<2zCUw;zZAO+!}XMrX&{9pWyvOsdquxf3q)T zQ?H-V%d3xw3iOe7+lEA(W#!{BC(fa%So1M6u3sC_T=|Cfct9Q&Y1l0Xht_5<}FLz}(_9C(C%D%IIC9%-S8H+`!APWu@H zq_mXWOr2UXPd+ca^NAHO@fuFT8bEvI^juCbcvvmTrf>bFwYvlygI_COB^cQRL{yda zKDbbLhBX-`ZMX#4t@V#FjZGS7BH$JxWEB5G^j*BN_a{TjeYyZbZ)>V`dU@2GVr+VW zR?m@F7S0(_a}7a{RDc%qc8d2SaN%alyGt+c3Bq^03~gBKG!h29Km?X_*yR;Kt%GWC zMM?n;ZfMga^nb8guekPhDThGc>%9Yva}~^R`S7?pm?|4KU)g&y$yxk;qsQp2d(BS% zl~>>?;UX%nf`#~WYc{X38H%>cHrpa73za(#Q15V23GJ!!c|$_DGnPg+oIVVem18Ic!}6ZcHvT|J{*_ zI{8*$*c!5>N62W@mJ1%l5L9R<(2ZTf#Dls?8ulc zu6?0K08?suxUNn5t^bucuCCddIgvlW)-2V&jyaHbb`q_yx(A45JC&+}2WqKN8qNUb z8&v{JMQA-7#{YidW9z5^F5j!jF%Q znm+z}E|j_+${xlHfhrB@tC0{YY*|iMvOyeJ!S5cxKywV^W5zRIa@jaN9pY zPykk(DqD0LMM0sv-R`Cj+dGO%@#CCNZR~NQf9D6QF~_fJ+-?r1gkFhEOyj7m)T!Tu z?3Vaml;@9o9R3Qd3U8z!9P4sSkXgo^puCGeHBiSkb>~@a1s4LO=dx%4DKhevea;C;_B~9hEsK+pQA$!8{ZJq1upVt=Wc z-LKm&mF&QbJ_3bveucOTG_Y=Y9tiyJybFs!+V`3ql;dtX02n&sr391Te$cSug}0pP+N2`0L{C!?++cLNaPE&~-y)5|8LH1Y7ppD_8`O9JuIuM~g#8=`Cx<^}Wxy@E z!gKr`9}`1k){8^t6{-$0LXz5^b>8(>lh4jCxBDgVJu>@S(T=MEtcp8AEDxJ6V3nE8 zr6b$P4lTBjoRC$C+Py{*QPHxs)7d)-lvV6Ax!dX?qUu*5w{s$g?e{^<5 zw%Oe)AQ_M+<{D$c^M!gS=cy6-fZ*>JLy?Y#HQmco1?Xv{%duK21p1t6x0z-Nx*3|p z`3HHKY9D~>x>b46iSopr8@Op&zu>&XFyUn_iwT`#RIwrIqHn90c8<;&C{Bc5?i~>e zGVOz9NO_mC7HviYX;T92DM|<@>F)2*N@BQCIC9WIiBi4TQ6iphPrTCK@J-OJw`Jw$ zcypYXmnCe{kt*W=w~n5D(}rqhmU-sRolgBw5;o;{pbAf{I-u-C->yBo@utwFzYk~X zpWa_I8)EPk37N9Ou(LPZ+#6@b_pni17PCM|rFn<*? z>2&Y*3xLuTQT>huY2>&8?;-C*{0^3Z-3t04NG&clHVFvfFU0P2imPkwI4L`@d2 zL3h2O3P0t9-9;k94u#M<2uhTXq+~>6IHs>+#wgwH2M^(DdExiITxJ*55-Sh2@Og(R z+j~ZjsbRJHD&hLq?8B|@#f@y``SCXJ6|Nsg;G+akiOp25Jo_U{Nn%|?4IrAmREctJ z`lvWZ8>qV}f5AXBfdBM6Pug&EWhGi+US4c{^K{dKMd?Mro#tDGCUZ%$q+^g&ws*Ry zz$N=7^~bLn0se;DCGao2Sykb=FM`u%or0kB0nl_P%gOw=#{HJvEXD0KIYQnB>YwsK z=#{3Hp9$WhHxNCIlznn^?eR%X!tQSWb&OngH4`v;uZj(HBY0Zt6LS$+x3VDp+^Se6 z{+)m!i`zOGoiR4xwB?cB5WC^+#SeTkWArg*M1yjj`z}6WSL7+{k}13mR-?Y_CpgwS zoYIA(p4t(ygM7Fja(R4TVumdB<_E(9kJe+QujW&i$}0ahr@PGmfB^-fjy)vQhNR(g zs>28z9m`s3JtKPpyFg`xIndj~gV@8L*I!s0QleZicz+j%=CYt~oC3SGa^mbNCk8Yb z^e?;=6Pf1UaEBD%5C65Z^)9XR6!q?Uq(#4F1#dWlfB=TQbGksK{5yCUoXCsw_9LCM z#LQsXaogrC#VDMHdGAcB^H;a*?~BI3hJ|*K+*)RpAl9)|+CBBGSo2IS$qW~DcEIlA z7h%4kU0u=vqxq15IV6!Tkkzs(hW;@frqJuKU_b$2Ix=RKcB%04UIRdkH|)B5u^~q zA??!6)pP82`Y_8y{7?A^ev85zvq_(i(!g2q`fF3yc__spaxc2N`T3juy|hQKNZ!|LiLv|@l72YB_}J!oy@6Dy!D@qWe~?bu`kLW zfn`m(ZU(*8Lc^ZoN9(X&JW*lsoNq;Fj#ZG9wHq6F2mDxIPxm2&HO`%k==3SdI$W@i zbwtU^ie=Kjb~zYY;$+_ImE;S4t7-UmehGFqA+`mVnAeAgq{o1(vLVS~0p+g%Nx|iW z5~S}ro=n1)jP@VkE@)w>V<3Swyt&&;=E}LE&FZ%Yz7-g8(n-r>{8 ztNK)cirx6P?KW8qxaWo(x@-O1YZo$SCPQOVH^xeb4S&RL_{aCjp>d54yYWxL*z-B5DdrE`DQEeXNQ-{9osyV6^G>8KcF*y?`qXH$Xn^3r+{9q(GLH z5p9+YCr{)B2bN5wz67lch{Rx*z4H^EjdLOpY9#__t_Buv5B-Xfruf#olhOty|J=kXh4NNi+?8PB^$6pwR z+`#?Tl3h&1*eqv_`dh|OZ=rCixqL&MF=+w7+ODjpBScg9up`ld*dK7K zg;43&k}S=4E?}M^?Da6cPepKE1{1X@#=ANUk~|dPr-~?F058NRJ+1}%xS%zYHct#j z>R439VMMz`EkE6f;ByhmVS|DPqCSj6>5tiJOU8ORY;#FWyWRLAd+nowBhxCV-MP{G z_Jr5fz-lOtAC*#p$zSt=?O8|)< zF)JRWgr~*;NAe<=u2dLz((kRwU=2H=0X@-@FJ~u%!DV-j^7LF#N6}?PxK*yI*#E7) zA>Q4*07D7W6K)SA)MI#(?q(cCXa0JtX&_=)a62)vX##l8td7pO6?Y=^VM>DHc#slh zVo=%Ycza!7jeW7o90<8ZBU(L`QJ|$4j}*vt?3E=x6Fes&@o+U#{g>hCDxgohevNQ5 zXzqF4O=~sQHs+y+QF!L@^hG{bL)IHwnXf!oEGoDTZ~kRpddQtjdQ7J8 z#xG*-7rs1Z zZGLn_R@r>5+Tme$ZHM__nsZUUiSJ@bJ9O2nprk1T?ESA!L znS!uIuV{O*6x)8hYS^Sp^#&a5MWaA2`kqf*aPA|k-S?*50oH;U@owm=e8h42AZ9S} z_h8VUv$x}PmXiEdE`c|zk27cq0#=x_@Kh8*j=X*Fy$sRswlV#KO_Ys9`OI%e9my}) z-InzD%3iQUnG7Q0I&R3ndj6<#jEN@(1;-|-7{gEBOEeS+qS9|8HxPuF*Md0nSf#|6 zJQXya#RK#miE*v|K$PjQBn+rn>(IMet^WahU^NZY9vI}W>#-Wj$*VsGuEEtZM49B= zBQsj@%bT3v8nU41m#q0H#M%*Ovffoo)|C&7Tk46~@i8~2)aYV9CXjmLx;_KtcFJ77 z#qv-1*urry%Zsf%dB+d4uK&gDtIBD>DLg>zeH;F5og%le+IC|5*-s(lEc8^^-V5kU zmtv3kX}yMrP{U4QH0dvRP_{5DBdmw>Y2G~*G$f`dpwzg#I>Y=LR_ntr4bVFlLvi{E zUKJ!MVMDlHiKR>ZJnh$tvI#P;G_is-R`6O+<3Jwkl-XL^1AXVt|9lHL=LIffX%zxJ zp<)^ceHR?Y`k%+S>f2l;!~=%_D(=m%FsX8AZS@FA{42K>+9m=uS4SG z1>+hp!Sg%D+rP;~Z#JQL<)BZlCniU4*Me;yY@g4^VP|KIW%wrJ;0$ziB7qcT&>qC$ z*%K(7r?4|ascX&9yxT%^>>~Pb*6Ud;(4n7lSuNb`@=QdEdZ>)2&ylT*89bKq92hdb z%_Xs})k3_;NJG8pe`0)|Ju~`yuY}!z$xhUc^qU1(lzQtA9JG2hEk@kuCe(%Y#ibY7yn)MQItZHm@UjG`R|9@H5;{B({INcs?#kg9`e}8Jj?FNO2J>*k!ScPKw>RK2MA&jXpMy5 zOPCC9ITc}rnJ+v$ey}uLmhEA;=g}MD*=YqUe!@=8AnI-fl+)CTv4z^roki+rKc=Ts zH#^}dmzbxu<`~Wx#qwkYhj7w^!)!OW&OI7Lhaqehw20_-v6|q+?UkCMSJR#K=Qn)h zJaA_W{7L$Ro1oPe15M^c`{7;431@9~Gd(K=^r)u(Yj3LswCZWpDlO>jg77F_Y4u zc4Q`9L14#z>t@l$9a}{lN4k>sj^|rBFnvFKkGz*_;FU)$Nj;ke`o^*?8(#Bgh+T*! z|CFmXu#@$|`s8ny?wiz`h;M$$&*l*ZR9VfRh9ep?Y`UyFTLhP#yFIG9?PPwmJ?GS22@;sc!utGmbLORA4LU(Gs`X-clHbW6_ES` zq6JFBnX_jB`r_v@O1{<)43T?CW_w|2Lr}KfA$H?6CU(t{XXCD>Pb!jOYysWexycn- z<_cm_r)5E4NioS8g7zP8-}4FvJadX}*|%GeSC_8OmGP`~D=~sYwtRLHthPJdGQz#5 zMa$CFp-&7g1A2c1AAw_iB$W8lu1A=P^9s4T;jv$=(-_y-E!%YF{@k(nG>HwNyuMrB z=J@`~b-)uz9|aSRzzOCN;~-xgOK}r_nl%48eE<=6?2IWSb$032XVY$|!Hzrac7I$V zy-GQ6Fo#NOBpdaBtlp63kQPBLO;smiTw386>KU*t4)mAjNc}^p7a0cv>vx40P>=&{&tx5YMd$)+zE7oWg9Y`&qcXw|d&ik25XbfOwGqob`*eVZ>=+ zTL)yvF7k3ZW&`9qp-0byaDoqyrgs&n1Qv->U9~wm+sWQj>u^bx;uxI=i=vST1e>+i z;HKC9{^!EP5K92Ao5oq-Kc`$OElwQFwL@Ch#KYH6Ka2PC0hzN)y(Q6YfP5WR&fmct zhEsUobTKe86tj(Zcy>f(4K`KKh@NfmOM+UVFAq?2)-wSJIF9icHE{rR`(fn?m$m(h0RfEpZ4lcA z`|}04*@7}V-+tj-A7iPMTK!FsYNX$=sTE||+dK40>HfW1MqLE|Lihw>98|#SUMONP z$=&JjnDLG+Yd0R`4;9WeJQxWkWqm;Rg(psh~Gz2p{~+{DN4eZ3bvhE>KtK?T`6(LJMYDDN}h_LFLV1T_{e_hX1T~e8V-@c4aJ`GEn81 z>yVI+zY7&ndqc^*<#ouYn!(Z~jkc#*FjxHEp!&B0^6FOzq6Igth&r<;{asyAGEvxM zp|)l=pZb)XCA!}>NDURd2i_m;U>EiIX=iIR-H2`^9H#V9pd8n_eCj8;RAOA1!aWrO zp$zub-R=YMZkfdw>>^IME3P{MLR~G&=HK5$zO6Rq|38-AJ)Y_R|Nqaq2$dXi?5q=# z#2hvqRVwvX4mqc<aTdGb2SsR4S+0=tM7vk@I1j^D1nln&UPW!`Q}bGdq2KF2CQu z&;Os7%j0st-EP-wXOj*!vZ(09xZvB^hg7F_Gl=lb*wHPW8&+fuY<%>gAoQl_X1i^0 z{I;|Idv6slwMxov+JC5{saLFbg8n=z)VM2c*seB-WxZfD+G}E*qLiUrb?m?A*P*?d z49xu8eBvr;kJbD^ZJ5pPZN*>w2WdrrYK)H>mOlJNbsV-DH)~0f1Ip8b$1T*<=l1xy z)tT0q^pvxjUCIXmUr_d9 z=MI^sQ3kW_CEF>`7e43BZ^8 z6sen%7B8TyI5$E=;hGuXw$76NHp;SaP}?S z&3~A6r1C=3r$D<5=ZtlR=}~chQ+>B{nEL%RGL0FIpF}Imyvj{E;pFJ2uR=Se|NCFS zM)^0g>a>h!W9v*HiGEwO9#}r{7_rJV;Tm&|H5&WqP3__3$u&xnDVPCgT@9NI)iffptBt1p=-7p+7A| z&(4o%dh5`Gmi_GOA^phB9?PbN8i{#Uspf$1vxbM3upO2LcPc zr#T`kMaVCOB8~fY{jt4hf7_iw`(WiTXm>)iTbpxE83_8&?A{*N;Pq#)ps$*4*IftjeldsX#*OhUSJWOL$*50M>a;Ohf!f$TJwh4;TEVK}R290xQ<(umM*OcVJC_nZrO;KCz8 zFMhI|2KeL)Cxwm7u9H?EqJc4}bk0hhw!=S#BwqrXPC>f`&Y5BE0BlN&>G#-uy9n;s zWGwB@w@`^6d#OXx`q6h-RqeL_a{+d_1nre0Kehc@6FLP+v=;RnOPun&50K zv*}u~WzVffz&TuZ!#i$CiuB5oTk?#?tzs9B4xN!4mJ0&|s3zTo#uTpKr&8MY=!p-v zkF0mDdyXGtR}LL$I~+g{?g#t72}??RUG3?ugXTDx0cJJkoo4l98`1itJYQyvCir7` z-4hL!r5(J=TTVuSYKfstwn^4Ou&|7$PXW8II)?}B3?<&Dyq_>Oi}U@w86L<^5kkyKmrK)_%LsJAongLswaNOA)zHD=7x^Q0jNJ~Rt zybFwVKsJ7o4{S}mK1e>rVZw0r&~*d=@F;DIRp7_3s*$6HFDG)C7i(uy53l6|p{krZ zk?F%ZzM4Vk`kpeYea-OSxTe7J_r#v)_vDk=!157cmUsa7IpnKh;J{=2+#G=|%;neH zL#>t{j&a5|d$+gSpPgnq@%;~|Lis{W#c&aUdl3JPO3P2JY!4=PqDA?P#@?= z94qT6POb@;v(j;(M)3BFji4%~C zpmF4vg9qj#p&8HhppQ|NbE*;F8BH~8(FWW94y^m=s+0Ni_P#)K@R6UC*is+||5y{3 zO@E*sb)&5;9_Q5w==sI)zYkOi-rR0WqO3Z|)d+Tj*Bz+2PQHExjA8H_D<+IU4h*VT z4F~}BCi~`GwsyK!?Npu21d}!q&(_9*@daLj#nbg37(Ob9UOR#CNi_kXEpH-m# zz0PV=vuC}#B0hk-t;5I@Mo#@nJVe!%V#_8|H5Z8=4+Y=RCugFwoq_A7P&~({IQknl zEhVf`i#GLoFJ78tephQD`a&=^h$Ur2N9<>F@gAD_IUnt3-tdIcn-4V#i#|RvaN!I% zk%z!bdgSqJXYfbU)s6a=lj+*v+c&d6@a`5@P6=}<-=zdU{VD3@L@(&&a>caX_*1Gg z`Dn2J*YHV)+68UvD;E~kr%=LqsBXYFXoK!O)s5~LX5HhG=7Aw`Dd(Y@>%Xk(16(|t zH~iH8<0p2s1IWVQprHNHk&0QA48dMt?6KnO9bVogMp!Mv$4?ekxRj}_MkL8+tP%6T zWl=Aq+5)%V1FvxMB}%BbnMMp4TMo!5HlDD}^}!s(lDqG33K;5JeGjAM><8s`22fct zvu!Q*YD3Z|PVA^75d_!89NJCt*GW|A59a||$tOGW%0*Gbw)oCi&E&u7sE@`Dz7k2A z{L=IZ|8RaA{5w2jH z<|<42iyp2inm@T9F5H%(Aw-aVzeAgUiII)ljI(NwA-+8Y0!jb-CoByyHqGf^@kU3& zdIii=9L^kibX)BwY9=e+Npt0?BBYvEJ43$T_6JGMKxp;);D?XttJd|vYeH;gH?HsL zv-XVAmuhSFYFS*79pQ*7#2%Z;QHjT}9%;y>SQCesidQuBWT9v+EE>*9_qw~Y33UAo zG0Gp(>-57Yrp^lEG1=b6&7QD5nm7?1eLRD%D;EE zBVR23w7Ray`wkDq!Ua}P^y9RR!Q@0QSpQY*CJpgq(90-V-;&R3@~M~E9sUXR(V5Q` zkL+OMMYs^=H{$6m=70B}+oQJ#y7>6FG?8rV{`?R9M$p+&H&>>2vKH%t<=|1!214Yx ztETCRw>GZK7!xp;_X|9scg1NYBJoOhbu7_EB8l0oJa78_&Izsy^R{4R`Dhrd1(<}} z4-OK8g{S)~p+V0fIP?$?4(o5hfJYZpyN(6zbmY?|8Q>nnwL9A3bFn|yBpbRyhs6W@ zljH8qr|rZu8Aq1yJjQ(&#ipOT#p&D69qy1!JJqwrM}EndTPPfnB7!$ra~$i7iR={% z0oa4UhPl`z@B#JE_X=4l5+!c^Bw>V80xZ9me4=e|B#;i%p}hJ@vUVtG=mKx9O{Vtd zP@;>+;#H3(2H417>H_)RW))16$&p}aW|Z(V8Y^a!`QI(AdSDBg9%93|yIY(Wp2i}w zJ7M@kv@?ua_`-S$N5+c_8?nq-e>o!J>Q1v92m0lTKW}8qTr+z@&;$jUY^Jap>572! z*ebHSTpv#Vsd8}xDx^oec7bX5jF!8@_VP0miv(eS7BkP(@d>=?ZxZJ05%I z0qw_8Aq3#iYq@HbNn101vNx}SvQx{Nwt^e1(to)}D(SL9DQiWml(6azXwa{dFm&s$(p$5X|WiCZha>I{-9oR!rgJBS3_D$+21XeM^{W7 zqERj6@SBtUa8K6pzG)F|(IMKx`OQ=O)|ua;fV+4S-(Jb|F$&Bpyna;3h0nzF<;a&{ zEO1Td8e_q1yf-QQ3->gc0B+#be3#@>nrhbU zh~s|aDURsD!Wwcj_|Nn4-J`^q3DkR-W_}8yI!*YQ#}`fr0n=4#JF$(3hS-YWwh0@9 zB68C8yC+^&Gei$n+)H52wW%1)1=x~3`aQOPCd?$~-UyFW9GfM5pEt(vVQr%=4xu@T zvN)2EhS7G$G=&dhoPWk@K&ML#v6qJpesdL^PAnX5CaJ+!@!HTw3W3|Ew3bu0A+))i zO)JZrvSN^fv5BVt=%f(H1KZ-W%z&4+_FK@p0eh5rcAOG>tIFW_2P#hH{mzUkyiBMG zHVN9_71rZ$Kc=HS-RUksFi{ia59c?h-Hdsc?6%&eQi>&@9r30CND(y(@m*0~`4q1; z|I5B|u-K?eOl1Aenw!-Q{|WGLMIO&$ZqUCtZ^;P>#RcI62PWU`44rjuc>!3i%6zl{ zTCv|8J?Q7S%Q2j}8hI*RhYcRa#4ufJe;sllFgIIjT&KmwP((Sh0>;gOzZ7 z-xK+HkFTR=q`L^G^;YAGl2w}y5mhl440GX1{`+&=Kl2u1gC-!{PJ|}su2h{!U4wA> zHbydEP<}(Jx7Jb(o zJ=w9r><5nIhxoYE*5uT3`MKd_@4mnEm#7=w2ejI#o6=QZ6)vR z1JH!%Y$63uGE-q%qI4pw|B7u)jamuX_JH^X00@?(4-+Ty;kH*H=gY}=-#G}Zix;&V zoK}tyyPbeA_IuvCr*Hqi_yPHe2at9fdMM7k)nl`G+4O&3)~Cwjcuym)rQ&$;P?Psy z)yPo0vUJlk&bP|LHQj9?MZiMF92LWcOOi7KFM#_v+MtGv*Y=bie(p>>&@7RuOv?(X zAbUVt`HA-sf`L|VMJR@1u@#M{1^0DEl~dOt*kUlBLA)K$;qv+|LPsj-+X&F!@9ziH&pdv35q zr>W2TY8;EfO!8ySUg;%DtN|Sf#C8gsh(gG}pU(1_bBJ!oh{5a!WV4n@pSTGd1oDN| z%1&0}K&2~>CQfW`*nh&^kO_wNEw9q6wYmPky`wKPpXTKh2;uv#%;f(vbrX+no|NjK z#bC`N*jT&!8DcrS9lY-yQ{c3O%Bh;#q*#-qU!bjBkdyPwQo zLQ6AJx8A)f+mi0f)lUX{4cNPy-qX@pmc*4(HCP>@Fh%hYVzHI&H}DsJUBg}Ub31!u zUf@*g&seUcffHG@@^;C{0QNWyHKDqaiPKaIbOL_vxFJ*S60&Lbaox=E#I{ zD)BZ9*eRyl08^?O6j4EwRu!`lV?j&w+x<}D7uOZ!y^V;~@h3uqKDwGy_sW&?OX|2B zCfIurUC%SXQ9OyO$&p$#HSbE{ebpG+hB1v5^sdmZsah8JMAO&Azf!`Fl~CL{7Apq% zENstO1n5_{pvLCO#CXriXOqK`QSMD!v;L$xXKd|nVe8#zh!Dt#~H zdk+%CVhHYn-S)z!n`7%pvx_T4jlws=+lG+qO2-82p)8}%(| z`Dq6~HhZ|nQa~O2IPniImb9)dTuaXG@lK^ycrWFN&Tla+-G+eqI0GX6}gv;p1jup6@fUlrcE&-u9r)NjSlVe%`(?|9Z_mC9;H zEWdFxNAElGtE`L#GNE$brf1GJ?B_vBS>HROPiJib=|7JoRrmgBs_btr+N7QTLHlp- znn2oQchduT1?Q#7KiX>c8~bxEKd(#yElY_dw(K)tI@5$WCEMJ)bI#8{lX6OF*X*?` zTh+7f0FlCi_l5m@bgKWW3!C!(&iemg zucO3ZJ7??0Hs9mGISJY_Kz|d<5YK5%&D|m>GT&#_)1-p%#di}<) zE8O4guKk`ZEyJ95y;B8MSCshM{IR6x8}Hk}`Q-Dv}VML6Hv`W81=xc)9%) zuGmxOIpf6i&YR6@!tGqiU*f@^DI4kEn`E{$Ba7JB9=|sU5K7?+?i-sJXKHnP>Db+e zWX84PeF72Q68EAUc&9Ir)TBWLp?|dCh}&m!=fiyPpF@(?A9}*ytK$hfg!y&g%8`Lj z&%^nfvW!Uh30u~XvoFbxXNdF@l0!U%Z`|4Y$lZn5I(FK7){l*?y_{Y4Oq}PWbT{`3 zgR{uJ$-@t_>byE%yur7MY6dy^(zU%o8&wR4l3@G8!FcjTdoS1clPa(UrdS|78+{oI zf1=5(SaMdc{Xi5gC4~9=E*t9%Grg20om(5yM6H=W)i3 z9GqpyBo+107$|8~S=UKeQ#VT2w!_}wII7=Iw=ZekfHm&vvwkU(>#oem8uA~5Cn@4B z17nk}_S1>9zJ42Bw3H!Pr9vA$jaKgNy^;jj$sWaLZRo0hZtaV$(WL2p-@0#RT)3}L zh-IEb)6!zWt+eVk8!(i{%_xj^ZhE@>!5H56M|s)lH9~4Q5VG-~@naa_Ipfiek`K*) zxu9KEo4P={h}}hQD!dDgd@c0M67-hl4d}kdss7*C9N1UR=QpAzKvrN4tte5=*8gX} z6Sb@jrMzC4EN%BVI{#EnxM%6;F$dQ~!g|QIK746j{ROkA*-z&7HkS|Ru8Z1CgOU^7 zOgTL8i5!9meLR5_-kO*OH}hH-N0iI02arxuf|mcC=@$Tj(NA5c%m88Q>M`=Z#IGgt znoh@YcFJYs4q6soewtY+r0D(GoQ8ADEzj!ZgBDmLAxFFzkmWmC7i&RQ(G&5Q$q@tr z`%){~U?Gz1E@^0X+PI9SnV2ee#-9d?@L_wGeJ6beIogH9%KmTV@8+FjD^}QiZ zx>38~W73wCSVvBZF9A~BbNz#30`K9zo5VojkVLu<8Z`=e`{)MqKbU6S2Yoq;hQsDX z)$|-%P3?3#^`I`0X>iNDRQO8>IJe^$bqSBLo1Jsc17TT?n25lfa6=`I%6#tWpCBhp zTzQ8u?vi*^{6b%Hd{5I0ijI@uF|KU%E2%wA=!0U0@0v2It(!4%4`BX-X1&57tJquR zKj5o;=)<6iok@e%?pwI}|FZ1us&~e1kE}zFTbK3nq3EE5mo(P+JVO4k&4j`~lP0t_ z|H)`YM25BfB?;bw6E{Tu<9$2Fc?>8@jJ)IIjXKTSE!{VJ&26c7JjagNFr6DC0j)Nz zBb`|Xf7wmK@t?l9#(%s3Qeu8^tb}nhmIWVg>SucN(+DI&3hMAHu`BJy2cy*{Ps4@7%RoUKG|C*H#8 z|8&+5UMyKBjECjW#5>%#(;T^1W-Ca1e+R36>o@$HSK7o|Z~aF2>-4;Se zvvkFZH{@8_U`=Mi;})>8n(jqriZDCHuxf{c4z~+E+dnv2Y zsm`N&@KB1pRwYp z!UtC^?lNsVnomha_*0z*Ej+^&r;fUI{HboSb_1F~ni z-`aBpIi{VgCB?3L$<24Krj3EiGh`oF^?J~~vX5-7H;146e|(V%{nD`Is}_RIQqAWf zz2B5Y=M`<1aT~*b!cu9D2c;nt{XouAa?bopUuI@5IY$o$>}b+ja4z2mimBfyzQ6)9 zt-XmFHlqK+kLj&u8HG;shhPkbAPG@|EAVO62SYnj>d$LVDcJmY= zc=v1LgUgHl!s1=zBkdmy3ycDola-UAI!phmM}MS6@ii2%9u(U0??yLal*{%xySl*?6G-izLTg6u-(=05d1g7WaU_E#2GV*-4w=kgYLH%MFi z`p-c#4$%)?m9AfIm$?>)ryPFUbaLi%OKQ9g=)YX;?JEfk{@E`=4*2zJSSBAp4c|OQ zyxPWe{+-3Q6-F9&u}#9hPCW#nmSQijbtcrFN?`_9s5g$i(r6t6ef9QbrG*{6LSEeY z<@LGKZD~E#KhA){{ClCh2&p$uFv1srIL(Ai6|*CKlL?V3VcLFb_8H0W@fG-Of}NUu z%wuy_xQb8>RkzJ*>q`aFwK(LI7LMuik~yBIVm8%>N~XLG5FYQZkOAFHZ0<)16;8OV zyKHnp)jOPsYo`Us`UtwI7q)P72 z+rzo;wF&nFuv&%h3%qYkru=B_g!#M0SZ^Fkg{IcP(Jjn*0CTxxNYvyp_d>yQI zorVYt6mPqHgBasi@Vyp1t{n~x4=7-Vf1*j``((e_*Ct_3T*KNgD>T!uHgZw|^%^efE5d{%Kb!ag~;UKfD4m6Zjx9)gg&R+GbqPW>m1;Q;bn zGslav(W1RE;md^7=$B1q<`7&u^uZ>^Dd#HP_Y{1}KjKH)(O%Z5V9v7*wjS0+{V~B< z{F+ounDWPeUo-x;yn~6D7)ozKC!1<*>FZKkrfo5659h21AHCen%&mmm1PZ-1gyWp; z9FU#Je0=5x%lQi3=(gYkvsk63G}=G0O)!VHY|j+olXEi+HNg>em0o?2|5(qVmebZ_ zA<+R1&F9p%0Y0z-p0+W^=bhJ_BUhggFA^hdB<@&~zX)HZ`es}(Bx#%WcV|e&1wV`+6ry{BNQ>EE%aH z!6lLZas8f`M3gYQ`q6=$78E=`Ax%frIf2`2w^7;p|HM%>S?&I|+Mmw~w)Y&BdbuG# z6fPJnY`dcPeIi8s8W_l1Etnj6bm?3+yZ5scOa3aHDIi@~Ttm*q4~2XaqW>p8&Gu-e z99p7*578XS(PQ!0@{?G4GU^__@)p6ezu*m)Q<&WuMlBY-5iT5F`KF5G{RDYV7meWpJb?fqQF@4%OdyyDHM8hj@}s&&jlQOJ;vt>>34*0|n2 zuvMFx1^20ar0YiVv~|<1o?=*Eg1_1cPJ*nNe8&-0oo0W-a3wpd(ub0lI<9?7clApf zM1W2#OcsNB4A|1KNAJ&-DfVZ7=P| zHOPtQDBac&@oK=c#VTKA%CP9ju!(iQ5|)O}Z;uI*l3{ZWRePBNN@rg4M~hkT$t>&- zgK5OO5t8G5;|`aTSJV(gD>VRFRDH`Ks{ZWfGY@*f^DcoytZ!=whf*D-RUP&p&lOHb z!tyJ|8~2;cp{FwKE|(dzmw!6&VoKLLs3`Do{51g%T^{BTM<}ve`UmqPemz~ONPgSW z!_+)!{Dk3r1n=NgLEQMwhlX7-9ROld{zR!!e8^ZA$AwRN_ohzbGB&XccXUFGNirE& zvo42ydwbM_Qx(>uw_MG(+|uh~{xEeD7@IpTGa)GVoSB}S@bnm;U^`%w#=kK8c)iwh zq)8BJ&n*lj7a;MYXrWCKZH{K&G0oole%u-iKxJ`Cb-9y;U8AbTe-pkS&TWJO%DRsk zJCP9E`m{|7W*isAa9WbNcGQ@wz!{gdelgW;&HuN@6kcLsz#lS9Gz&~91$coY9-J8X zW;36w${A6vc8xICm8IEt9fMXYT84ZVDOnq0%7QSdN7V+*hlF%z1Z6)|$KB>1M=h~E z!OOkBDXn)o;b&NqMU&jxHT2#4p%CxA!p|x#{RGTCBzC^X{C5J;$kCg^lbEf=54L{$ zVxCmz?Jxt_-yy<0Zqb0@ytDFl^`(;!AFADwFk>m*OrZ*SgXE!uqa$d$SZ=P$@~;gt zMWLTtqqQ&JHr4wB7^~jr|M#5Hj9X9Ej5B+$pqFKrWo@x`K?9(@XvN|Ep$$J!P`$fK zo#|8(bguPZ)t>^sU?u3zQVX(#O^<)?&CFUh_17?;A6%&XH&QHk>Y#9cG&XV9a&+`d zD`pzka90eMjx@5xJSiI2$~+!y^|K5(9*SiznI-p(;;kpMFGu3j# zg(SO?_&1cZ8RNGziw}0RT_H28V`c2iH5$*rA(f+Tw(q(=L#B6cN!L#FAlyh-eKRtI zDu|f_pjrKK+*RagP-o@#=`o;wAxEeGY%BWxdVTnCmc`3Ssh`sL;(Y`ue%RF;qoRdh z-Q_#WEHR<};YznF4b&o!N-D|w4hw577rwq~VfTQVWkD)wq8!MzqA+!DMY@9Lm2DVS z?4KMBg2`;~|N4H2EXnDAVZS4mJJk`FSbOTZ+&pZI#phJS%#x!+=7e>+uCr4W=8WcC zT^fV7XIP17V|Q<_i)2%mcP;_1nuQ4VRcV$VcXzC^>CkvL`^pb5=NqWrOiYFqPhE3d zj_Eq)Nk5`3&b^axEwSE&@+*0e*#x>(Gy!VnZ~@+#ZX=Lm{^I`XKq_U)4^%h?C}|)r zshTF1dTfL5BSjhwB`iCCr6alCKCk6%E&kYp5AoYjX)w&OuVXXT;|RBQz!M1FX2s8P z9*$C3diE#~-T;Jiq1S(9D=%2DG%08V;g~M~d+F0V)p*U{!#PsG*5BLJnCWPQvtA%7 z?M>kq&w_oe1N-Hl$Nt0Q@uluvzu(^d)p_ZGEQ>W-c+wK@NBaYK{sthBJjm>?oa~ZI zCNf9Qkjq0->3ydx-%hFjVEFH>9~%D_f=yVaWL7}6t*q#WwmE50g|Mx1alib?FFawz zgEbo7iQHg%ZMlZsn}Gckq_w3xCn#dx{xW9p&Jq)EzI{vtUc5qU@TZw69{HZ_WQCnd zX{Sag%xn+cqYwdRR?N2LD`AsuSc6mJ(6;DU7)^2!v zRItQ})y0Z5kys=I_kthJ>Lr-}?!KUTR=9`i1uLXJeMF59>HQGMNx2i&iU1TJIO7&}xbDxXPV_mhr8X&_C!+Bnk!Kx*=s-X9H|pIZ)m9>V2=@ z)eR>3my*o={W;zV##Bac#aXxIsRjL@rBvoA zcrPX0bVvZOK(13ojMwp-szpKqf58``{4Z}yjduR=YT0&Jf~@Tb)%uY|zBZF7ycvfv zODMgT8m=hdEFE~<3&{v_$MagPM!GbD>bMd!fvvOUO6J~7sHP(*@Oh6%j5{zzA1v80 zT*|D;tcj#^)|1|(*X{nb2P(V6;CbHj-U=iy6ODg>TbdB#zm#Cjvmi^4ZONCEMX_0R=C5^56i+f{FN zFVt*88gg#v7{Rw-O5u^FxlkGf%0;e;o*IY{mg!Z$nGlDuz|KBCuhnjLSd*!J>-??y znYC>ee#Rw{jpU^-`4yEd8w4s#d;g{jaD8|CnbJR*`L*s!M1G&2hUudX+&{?x(?ky_&! zr?dlk>mndKP!8i%E6^hEqXT+GoMgSwAif~9&a{eI5ICe7#9wca{&2vHP~ey@Ctw!O zdEL>fYQ}Khi#@GBv*+s2s*sl-e$uNC{Ni>YozjR8*&7*?=tuB+NmB0v2Y$YW$at=6 zY@=tsEI_sQ!hkxc#b&K&72r&o``6)zM8NMw2~W31xko3S5ajQ^$i-{Se=9`?emMsq za1<*VyWS||5c z4zf~R^R7?3ZY{4x+@)(WWYE)*3NtDSvUtY%Vai3=42Jd%3t!Q}PM&?qSi#{B(!D`z zU->>x+?6o2ul-|F^_c7}M&?iN=p~+@glYKc}I-I=EguP=J_6b$JGi_Cp`FbK*{h@#9 zyZiAjKK&yF2?`d*xK3mY;Tyhp+Z;H4Ar*Wt_dHf7`J-aOsY70fYur=pPYYy0HA&f@ZPtWgNj6vvy zz`FV&w6=;30^OfBtsL4>im61&$u5cz?p%w<@EB4oD?pRBX(~~Pqr=^p8qdzu?HjI_ z{{`9&@|>_|F`dUBj5o9+k5>|2IBj@@ZzH{;@bF+YX0m|r#$XH48vfwH@KYd?C2DYp zN-8QbnABKmKI)xgA5rHLvT4~Le~y_4G+zRb4hYkzy$P9zSF|h_)VB{CE>OwBvRQ`K ziA?KbO}?{@0FKAm)zTSp)8$XhDVf}Os2a$tg~mmbZnTYP0}m%1O#d?(5a=*dpK3Qt zM7Y`C)0Q1fR#-N;NpN?Ae*?PtlZR@=>@vyY%zfZXC%Yxbj}`!NV_wn0+w7cL9Y=AN zzsyA>S6Z8<3MzRQssJnulXN7|q=nziI2E_pQTX-axB9Iet4{4l>+b>+1BPmQ5tG6h z`L!Z(8a^hm@-ccL3dF|*gnLH)J~gpzc+gZD+@Glu^lgvdb!y17;7{v3zWh6miHFNJ zG3%>J3g!(ze}y+cycogp3nHcD4Fs(;>r)SMGcqX0SM=^#>UY#RTp5CQisLuGIvpAp zPded&Js4C^{b% z5ueHgxdnBt2lU0QUrN3ZuIm$SV>Yan?J{{lJ3WGZw?RX9dRN@#G}R291#5GWGLGZf zcD6d{?5Xm1A^!}k`hHLyQ71c`Ih->n@|jMcCaUmNW+S0Sdh@ou&e}`8YFUjxl+%)u zuD7r@H6Co{dw(_4w{9$vwnnr|=)SZRq?7FQoEe54I9&rBPV!AyU>vqr!9OfH8KQpc zxNy)BnyvrnLc4@L)ynQ6m1Ew9C zItVtN5#_%($#kRJQSv9kkn@u@5%`O1L>hUKivL4EgDBHbR5HOL*`;*M&FD3mKf|0vO3 z)+W2f#0P&-vEDJ2Mus^-e28b(Q9v5@7q)t^m+t$I3A0)pe^mefC2S#nN?T!_slEdI zPXGS*%cvj(I8^XMr9IMo_aiv3V3M(?q%Dc}NO8!Q!^*@!tlL9wzu?(Dm zY3$!Q@bGUn$^?A96Q>xxo9{>wLyl=P_^22yCiFb5cgK~R*sU-8MGw3ZsSl8v8(OM5 zK2PCWlEYT?jQ)NK1UuDOF65E(2aw#gca&Cmt@W0&#>zVnZTe3VmO@9g%pwlg7%g+?qF;27dTH zJ@PF)md*_#D~CGngFO6oDHXvH!!B!#03LKSB?-^o;wxb9B;Kq13$Gy^F7Vcn+XWCe zhpaf~Y#1Bl?Yo-AtEo=PPLI~ebpJ|!Yd?DFX+3QzVAI%AbM({wf4Q>N)(8Fr(t2VR zHFAWxb1j;5{ZG{{SB>9W-+~X?xy|u^AhbN}J-R~+jRvjFS(09IxT1Wt?!}=MHW?U6 z2uP^Ui;N;Z!jX9SQGpWxpmV0?z3x??n_DpFVsG9`NM*z0Yn9pHMnvXzXo-u3b&x(4 z;?EQiZ5p324F%u3TiX3DJV(bcTM8^5_n$(UUTJ zrV+@~2p?CA_Jd{%Uv^sl^|_2ayoXZGS=y=hQ`}2xuf}dwhTSdF>+&v$Wyc71)JSj8 z{dRe7V%5Pfk5fJ<1TH@|Az2SOxc{1Nu4IK>Il+mYKcGizs`)iaMl&mT-)Y2N3!8(T z$TZ20D95Ci5lgu3C4_Jzv#$llY>&>*5HHI8_MLJ41EruRmy<=-fBTEx%quHuf5IJ&R6#Wpn6h4{ zzXUvvO=zvW8=$%hhrT})q)m0T8njHwAMB3bg)i@bY?fbGTG-@VtsW8H=1qWMw_R2r zQN#9BsTijq$uG46mO5=f9}jDLU+p|&4_QuYysd0A@+++M>zv)JS#m&o_svtL8sxoN z-!55B8uWSN*{emXpePdy4)e^E4`tIrl?H4^V&)hM=PX?}F`TbT+X>o0`kjjrIuL|3 zhokwOHfk;2`L414Pc~yw%p=^w($mM}z4_F|DtxlI+KlP+LzHP!GAsERjmiak_W?fy zvE^Uh|LyqU=*N&U)tw2^{l?_*>Sl6ZA7wQItZ-%drbe?1NMpY6`DiMWz7IdfFeQ%P zAsI6_Ui4$g$>A^#0vY!!s-QYg=ENyj|CqS3OK&^RK8`Gm zjl;keM%oDpf#wk%iB6>9W2DE#n#0G5P*5MOsR-WHh>Im?K(j9eaBMBUyS3@ro1UNa zSZDt7UaKw^Oo|m_rEo*M1vsr;s(sPy? ziRRR0>67PO&MtpBpxOiYY;&dy z|8tI(6~6E}HtZTH&Q>g(Yfl}9Je@j*EjtG_OR(JVx0j2MY1`nQ?%Y3GZA*eo3}V{A z^lr(Wz#(u|H)JM-CAe4+L7kI4X#1w9%EyV&vHo-7`12_;r$Pk{=kxq~nvxdK-|yfy z?Mbn06qe2*^dJ&b3F4*(!^Y=VfR#!GGKs5+!}?lE;ffu%yUlrlUo+lX1wI}_XUd}? zt{0*@j&640AXzf2d(PQuJs;$Kmde?~-;SJoxvkw`ob$Ql%I%7ippRb14O&efawTWj zui^Z?t6N!Xro>1>mytJ~1)$s?#7v_j`XBtyFpWE^n@C*Rg8>zU#3B;U)tzM4$=|$x z@y8%@&@Refo2<69!B6(!3fp-yp2V`5*<;Wop8HETJe>f`vg?`_;wS(@lJ3CGMdrV& zNEPeN6yvBxL8>%#6(p-LCNWuqA2w~Q4#DRJxC1z?x2#+qn1ysPcbj~?zdZkmzhPYE zei+e31G>*A(uN3P803HpaAAS;ciNKfOUMC!%zrbcJ1cd>UomR7HTWJkg+5<#SY^}o zqo-jNUp-%UCgCrA(EE=Yq*iWG1$kmm2nbP$K1}vU*$iLc_uWq3QF?iYmq6qtC#Y*G5AKfYv!02bu2E}aJOw5s zl@*z~o8&6p-A;Hp{fB$qg>b^Ih20dc*UN*(Jm{`Fv>ZM+s*m1dfM<(82w(hNDh1;Q z=yRLu%)})AzwK$UR6BhkV!bZQf* zfS36p!9dWwl#fb$#)HB`N2`ds?bQkOCm#3j4U?iM3u49^K$h`5Rcf}}^#Kr4{*uN{ z+5Yc*r)}yz*Zb#)uXl$bpCgAg_m9zAG&zn(nMF&t-l0jzI%L+M>}*0d3z1ORVluEt z-=r(aJ?wT|FIf%y<1ava0Q()$0vsyfX~v@6*na%~N7K1@GvUYoKZGKrl1na?PpRCK z+&0ryC3JN+x1w6*GBUfm{mHMCH^Z2x}}tiO+$Oi><@9W3XE> zjGo*0uje__OXw4u{Rs>N+r1Szize6XcO0Uiig+)$8bOyI)>A`hdk6l!2C7~Xj9XpA zvf89sAfnUDF+&nicGsi8U)Z@?H;?!4e^5I+WjrB&N_* zX0%4;0>s@`Ql_s*I0R!R;L{Fr3olJbT0MaL8|BRlg-*@-G?H2V0)X6@539U;bJtSU zs|=bm=}Fk!-Uk8w@_TucgF7xOe&Ahu19s?;_*xh3D>~8kBWxjt^}JLZZe(}8eK{4T z-yca~EDtt8Up%+6o#k(bcO~)WR`R%-O_#hjNUv6#dG4*6#&qBp9xzrCh#U*vQm=ch zNysk-h_F{G-!?>KH2iL}@n$O(LtI1KI)a?z)5Rsl!8t1CW|U~|8N}_?IRZCSa@6&XVU7|OI7BpR z;7zdE8Q-aXfgzW0pyP{<`@~!$136Lz%%>#1sIeTU)$#HQFe^Z&>uqgSqW9koOUDxPI-xRjj0JsA6%AGJ`rdnvUoTR&ysZpYV61J9lIVv8r+pvYlN zT7_!J(m|0F)MGGc+R9sTr}vmy)xrq>}6|Qeq6U= z`He1sOo*@6&<;qN4R5%V^2)wWGm%|JPI6G42A@MyBQobcbi_R=tbl0mon27FG)2|> z6mZ)wv7EP;Kzop}XrsPb&@$x!12xWh3ip6^o3bNP69@sog8ykLahFtWywRo)-0f zSPAHik82K(PA?2{Dy|r-y4OOn@v%|umDt*X$KAR7 ze_QY@lW%{|G5%s7Oz-yhd_U2SEs5yIDN9oo&2Jv0?J@ZLXYUT!+Ou_b2IOVxtU7g5 z5quV_3s(!EajJ8jr7aiH^Ay3Zs2qhxDX#Le&~?09jDxUQt_?3z;(}y~pK<@y!!o%x zMEgC=Vz^QZ_2t9hrlsZQR!5?SPYmF>Zu3H_7iI{u@@j1$v{-J-sW&gZXx>~g=GlOa zMp$UiX(cO3lVta)h6z=8T!T)k7z^b_wFMGo!p=Rz{nR07hZ^3YT)nZhxo8%Gb~(P@ zvenEi^XvXX1QutE{!c;tY^@NJV}X1O{F(~l$v|LdKa>Nt`* zmPb!uUM$YT@h%`m9Y~+4yFmE|yIk5v&aXvZe<49BVU z2Jg=+%mL$L-Jd55yvKwxL8OK2G`Fg$2@OxN56*+4<9pm#TJzKTm2@J+4fe*CH4 zQUJbh$SuS$AgRV-Fr%uiDTyT(yldRdLCgoCFEG?L24vYMDhG4u$&2$c{%X`;#$!{U z;>$UXDOzytC$}}vViyu^pJ)*@$M*5*_m?bAijg2$vy30S9fy7|0*bzHqnROHK2YeQ@ZX1R?MHx6RJ5l-2>E)lXVp(ncE26%56YL4+0lm?Nr{^e$j@Ym!FAd?xs=C?H#?XO;Kn>F}0 zllxe1MJ!bn8&=#E#723+Utv@cy5rl-Kc{+|7TDD()`$H)B^2A~Bk)(1_I@WGTSe9qlim<~ zd~Q-B0XiYt|6ssuR>&7CimiTs092NwAS|lIw5DyO=!KojnF zO;55wl@(rFrc3+7F5mAxJPPA{0D$W3xRUS#xQA(aJVq}NwH6$s8Ud@ zy7I8w+?AlcLMmfkkk-7<(cf};PaH-NoDp{f6%(1iyn^XbJ8rL=W(UOt8*c@G2w~1C z_vRvqj&z^apfj+?GZB)7>AhdC2>=l@Xxv03}%w^W%c{^;hTcSfVU+J9*`eht{kqOzHR0*Ys2< zbB^#Nry3GN5kPD2x2)ocE>K68ci@w!1N3U|zGK{9JOFPT+Otp}ioTJj8V{4GI@EJC z#@&6^o@t#UL-nI+PL&@w1yB*vB;3!?_6W7(SBIfiAe#IykKK%1+z!hl=r{%L4pW~+ zH+g{~jFbmX;SmrU#nIm;0|P9be7agaDP4BK-K6&Cwq1eZdj_Q1hCN}k+ral&!PnB* zNUnx)KvD%Gs_!NB`!W|H9(e-W&2Whsd~U|vCJ@-6xKpI&QqGe5@kIXRx?S;%@`p>$0pHR!ERQv} zhu{ebg3lpyAulHY#OG0|Etd_(#sO>BB%UZ$`?*CfJ?06`ISfC|KATNe1$)8t$uM_^ z6%C8vaBjyv0?;08Nx7@jgo72?X$6}}id5e$E14w?OGK1rOSzElBiB1aKi5js}u$vxk3%#?zPe;8^)z(R{ljl`g8SxuF=!-;|VQ*bVy5W{V z<1su&4Gml$XE@?_(%6 zP8~LkW@;lGG1_6$&xyqtTZ$gucrBvTE^W{FwnEo&ptTce!Ce}n@j-c6Q}5}{4R`t8 z-zhja3bz!!*sqx#6h;av#Iu)dU2HbIyuMpZ(hsVL`W}&>@>l~HuiWovXZMc6og|tX zs}u57n}~X`Wc=?nagMxyIx*|0*EViohy5U;mF-45G{PZzp#!}emZDsE2zIAZbkN^j z_i|m&m;I{}^aBSoq$U6@e8Gvpr-?k}(TUxPCDR8Mh^ipy>w#B$sB;u>(c;}?__2CK zeOcB^Af5Sr^u6d(e)U-pqF;Bg;sXYuAbznn&;-9kc(7c1|%kUPNf zMR7E9H${<-H(167>+kA;l2JurcO1e!Hs=t*0EDfV*|L9df2In5I~_K#Kz)aDqpj8i zdmvcrPhk`2Cu7i8W$#vw8bjW=Mw!i2cL*>HX25!J@R$-iXuYI3CNlxk{bS{TEs_BV z+%Z~s+4ygiEY#q~H>xDs{G*jtZGfaHonQOh#DA+)(wslp2xLqtHQ}TfC@kn+PeTD&^HY z0Q2^cUx6Ph_XMc8J#8|^3#V2eW;IDE{=&~dHjYN2#3*rpye4a3S|2L*k=CooasIt$ zn8hU!KHv+LLGOx;vy2E;yf^jDzpu@-(dsCyc-WM)gRs6MG91m&;;voGl9@f-7w|HS zh(rhJ2;$Z?wg7;7>#&d^Rm-d?YIrtz3baFpz9+2?H#;8Hf{SW;c=BGA?E0mD2S#{1 zO^Pqt3n|mT7|$r7spPzBI#9uH-ce@&GA-l0*t+pC z8o@Pdm&7YWEaz*@cJURh#jT-bJHY!E#t`Un;G!Lf7L@6~`imEFcCa3eE21Le7?Ilr zkyk&}QQw8czM;1+>g$@VVn~txdBes^4W5k)yL=c7>R6jT5WsFf*Bcd!m`H1 z0yjrqH~0WiD`H=%E!?@1zO7+W{Y^!bVR?rsa1H4%+KO`e`q59kvO#QSkbj&Z&%$I? z@7?zg{tHT*ofPbP26?R4!L+Vm7Qm0AsYPsn!MeBfO23=HAkKcWyj7E#iE}sY{$u_e zCw%TT4Q3ZPKp_1Ux$TmnJNZbk{gLoS!V?_ts(di;`)$|U&ur1hjz`I%kAb`oVjpR` z&exz`3}7th1Cs#fK)gA7>9_kM`vqfo%-uKyUMRJw|-u)5J{k~ngP+l8|84tbZTohdyLQ%{&KP$2MIqSkmv}4 zf<7u{KXjAbA`dyd)Tjo{NC;fCsC_8#hI7#!u#zov)x7act)mvjn^vs0))T88*Xyw$ zyEjv58QZ*JV7;rV*`ug;YL&;;Y>)y{4C=_&vJST3SKT<(j)v74TP+3a-Xo)8bbrBZ zZ5&Dj?dB42OGgd%PiaU(&HF)xndZBY1#RE&l-$K9zE+)MPZ1e1xFl9^Cg)263{}Zy ziCyw+Rw(qG32VhhlmCIV5jp~UJD}Oe82SP2zvh?rT}a_JF$*QhyOxW;))^LX7R?9p zz3)Xmvh#e7c*{fF{?s>?Jwfp=ifB(B;^1iQ`sSv^jIJ@y@FeB^)8l9HlXb*xdy}Ua z#lk9(Hf6nC9$9=ap`%$Q1+wp+qc3*G4KnHurY)|2^K&L4J-6FOg8LAsuI3e}^;!3w z1d@%mEcN3vB|&vo2~}5Oj#?B7?VKo@KlxE?_?C737xj9|=ye+Z+5}A&x;ha0vQJa|9*d97%0s>tLDtrQv2-0v>KVqc=_}WsiC{*J-H-m&JR#xUwCTyhe~^IJ5HDO)go`d9g0fR;Sdtd_ zb+kmyb|EU5MC*u>1*h*AhiDJk6dd`KH3xWGXnPiXE)wIj(9=k4OUx7l=6t#%oc&T% z;IG85G-3FC_**z*6B}bb)!9NIr!JdpHd}()eR_ zY03OU>ey6hNY3g(T77^f&DC)ppHjZAPXCk~R#~CiGq7#QoujhRg@}6LnLD#XSS{gb zIE5iJXYJ)S#+4QfbB>f6zP#_Nt;le%+Xl5v@`*|dF>FLI!!?+j-kZo3`2u1<%M2+At|*T658NNqd&cR_ zbkm7H^1-D1OIz4vajb17wftYhO*O3ipo(DKV)eB^ExxKvI}$P#iq1)ODmC#60(2^B-5F>_fdS2a-#ULuY7tm#U8_)rWi-7;wLy;9 zFqo}s&Z?4KnUK=#T%UjI3w>R@XY6bd)N+a4I`!O~+fRmTWj0IfDp{A>;2i zM;YzyO$jqFZn9dX;~m>=c+@p+2vKQcgP`rq%qlM}Mj^G5_Zu$^@q9q?q72@V>f6_B zB419dYS7v%W5cyegjn?1+Q+`YKRhd^-Q#^V1!vFTW~HiT2=*$| zyemZumkU2#NHvP5ZnrFIlTIpfrZx;3Eo>pi273)tX6J3p0~lea~VF)8rTv@yKC*bV$yk9?FqlSw&06YUrV# z+{JUfxLTE(v#vp#_JEFP%>AfXyjaG#mnr;NFSSJI6KGRyk_|IgTdv(?>;%G67`aD2f(h3p~QvY-P-TzbjN6Z zyGI6D;~n5d>m$HOquLLNkXt{Bzn*p&JgBr#B%r_a>D%hjP-z@?-r)DHT={tM$qQ&2 zC+>cyu#ymY__1Mw`*LPBN$)&z0zmf&Q+B|5a1SzWfo^S)Nf)eQ4r;!pzzE(apJ(KyJqVoHoB~?i7@u&FWHF&!~?I zHA!GU1lJUHD(|2@?c;op?np|}cf;4IS&bUcAljE7QT6~5mNa@u&fY(?cRlz;Y=7s* z8>|NA%ZIz>*~^7#RaO8kz#s<-^dGlU65I0)b4xy$W0c7L_FDVFxmzo<;`ojdw)Q;x z4_BQ-m^ut{YI!G#)qI}J_effZ#4A`*fqzq%GaZtP8&adPFh34A%e?r0US54X?_DOD zLKE4@6SmRhj{lQKNq{nN!8!K4`l{P`t`gOT#*9Y-x?Qxmp)70d1?@^~XhwjX^v3%J zfx6G>YYn#-aJ-L|_(Db^SH0^R^`lKmqbm~Y%5wY!{6>uYSDGhdeB+-8t^e3)5&O|x zZ5#=wrf{dvn&K$i*dDvDv5zeeN;uBfqIPBcMnW(~pmX)vCpfAhXpTnT9Ko_SA`e^B zv9le%qhR&~NgLS_i4<$O$}OS+sY-CDmCS_oNxxJbvYEqz7G7_|YR_{=EnRPxuE?!S z=g)mRedD~DF#zp39GOf1Zz;$L@h@~*!&tf&EEy5CD|Px44TCFNlq+Zi_$@&(f)tZ}qQFSt??tjgiJ{=_zxboZ}%P zOnj=`y@j5T!fT)-@rPgxU4qoou_>|sccKu}{ABvmS#Rszp!-GU)4CkMcS$F?;TphH zd-WJew19N6E}pS`-~y^!C5@Bb6*rBVpRV;AwY?NVN9m~CBiOV5sEdB#Wi2B^Ml36i zb$5^UBTKOJmW7mHLl4-in*Z1%#RuLlvX3u<$H8kzpIW3*5#%PlxbCphT4Jfrir2Pb z-Dfx(w0hU%5_S~3QPF2g^s#Ykjc7X@87y#jn?gO0e9bD)s(c33kqggX;PuoEXMMS} zlN##w-|rn2X^)>F7hGm0r9x>T{I`yN>ExjnY(&10Nmz zc$ayR*B)vh82!*@L99=Hh(yyyy{6OT+G?7*v|N$1t8}%D@)3FWh`?PBXu1Rj@)YR7+$qHB<4ZHqz-y zNs=tf&DD4~HOQdzn@vXR3D4pEBF(410+l^6Tw6G#_@|956pJg{!J&$(X z^0PCn8;{^9u(s@;u@F>W6xaq?69(}oyWWI(V1rLbIs0IXKFLn~v<1C#s2hP;J=WF_ z$4_6K?^uoMLj}h|fKa0eez;!>nd^trI=`~-2GAo#CF(_Gv1+(is}F5U^OtLvy{Baf zg;QD8kd(x-C1$%Nu?NdnoVs$-=7$z-LphVqMV>yO zosKp*{Bv-6S{Yeth-tf@bwzJQ`mpIs>Z9Z-<6$#-+XV@nbz#6M7~NZhzgV;6_i$&z zE-!o>pX+uVO%*ifoYU<3K!sXqwnn1%xH+NzK6} zpu_s6J&aj^L>x?MTajI_aGDZyyo-2zCMJ?KS#bj9PvDK<{Bwf2%oHykH$S6;@^B+d zK<8$YcBJuuvx6#2bTsGqlHlZ*7*1u#E93F1t54HLt-L!^TLQj450ct6Dq%fM@9pvo zA?uMpJM3Zzny@eSE6pF%D^IA|SVXYtOdc~6Ij%~$whn%_6e!HYh6A6bKr zrfp)#*F@L*5W`NLR?9FGrEtgBoy1Yby%ZG$fRO;qwKV9l-iZ*u2(}qk$-^R8Gd2nP zJEPaEZ(K0e&n6#1-)z9Z75phQDuk?z{!Rn>55M5s*nIK&C!S;XP)CCAyDG3Zj+Tw5z%zr(WYo1BK83p;P*lyHYdBj{$5bs0;>ZD4E*Un#^ zjjF;W;%1@Jz>VG5d43}8%S4rTKsUc!-a5Y&{+VlpBM@@H~=O68)^jlqd=)jjoN>em8w7!;T+^I}hJ||sn;_IcX1x?jW@tJ4( z@_~S=C=*uD0_2W^)0|hCBk&%ptIFr;U_E?7r6$2Ng$4PKmD79Q!C%`$^ca^;{@=PZ^`SFmxX=Jrf&+*vc{MitX`xiyeyZaO@`XJ)({fPB(~B1EJq@YTl11+O zB^x-jFoTJ9mQ^@4!Lh;;Y^nFTiuk5atEke^^!=eomWK6Xtx;uxx6DvHp$+nN)tj+j zR?6nSW%FGVbDZacE-#I_PT{?0MkX_9MeXBN`00U)7pyF%F8{;C#wqQaVe2^olOF`5 zn&j0Hk6b-XX5J*bOUQ|XUzZ>pJx!gk?PHg$R|6XZmkrC~^TY$`eer6-v) zFF^8Rtxj;ei&?#<@)mRl))XvTx~AUJ<71BE;3-bK>An!%;EhHFP1Dgmcj2EMkeW|euh zpx^4Yf@$)S63y{x_NfwqUC5ZBh`@Rv04Km=S-JpMQWGo2GFnu?glg-HUi@df{ z+ zP1SW;@gkb}$P0^l%Bs`yh>UUfZFbPAm>ErrcyPLP*L0K3V9MwoBdJB`9`k%2`^u@k zBRt%rlFJP$C1<+h!$~iwj|&5gwHaX^%6zqoRI6B@ohz_g|!81#om$zjTMh854Ue(>{L&<*&_^iHLm40gX^vx3Xh&irHc76 zjAy*Go7qPwWjD4owty2;8m3R)O^8Z2i+r6eL-y=Ncj7?GHTqLP3CvC|g}|Dw`ZVx~ z2S%Ny^Eqd1U-JyRhqvQnMtRuZBcGO7)d0HLS;oBE2Z{@eg+9ozaLS;1vz{ET1YPZ~ zrlbRSe#afroN#;Lf=-E*}`}vUA)&`N=AB2zt6Ll(!at$51l8#DZ5K9_9!%=Ymj)jmEtEZCSv<75h^+ zN*6+j?(7@{wd>Ic*`W)2w6h2Ls6XE0@T=7O)CMcAG~)5In$x&^W;nmPp2hzWK9>61 zr^NGt1e8L;JY`ODpL5Mre9v|YRy36tEPA8;ga}F)EAr8(vU0I&{=Czw%sQm@fo=Wk zIKYEVy5sP_Hj#5feK}J7mK8z*{5|6)S3{C z(^>|;uY9bv4I7r^98tM16gt{&8GsUmr8E|}Jn;_9_Qf*=0c}($IjDCHB5ewz)MhJn zmWp}&IUqcxMftse>GlkA7yVe(WL@+oCvzqWSS!0*DgrYcUQF8I^sx zI5oss93CilKXmkL%I-Nmfk75`c8zyyvZOu*72=BsX6`>C$ZD4f!gZh24SVN$Yc9VL zxSD7ClKmx$IP?({Waff(AjEe^%pI3;a`+;%=-#bC*YGW?J+R-YG9Z>OY!9h8sOp}f zzqAqYdp^@!F)`>zKmI4EV3C^=K3`K#oMwziNg3VvbnYwZA8Hf1U%}(MtNCiR(aF)& z+5rt@H06El2lviD@*zhxc_XxQ2Nr%zwXlWmwZm8D#zKwzc$Z>uZ6VIcwScXyGTW^I zlE{c7ezTv0c^Kh0LvzFN661E%_=7o_=y$`-Fa(xJhZZrsw<5 zV|)bhhNaXCGsc4P_4-m&^1K4wd=Vo-f3qf)T{ahlr!}W2tOsAKp_t0>?kqx?Cx9w8 zc#l)jud^mM3)q3|1frn##oaoq@V49fW1aPz&XT+}KxI8^dr885pbC04T1sn9t8l1z znN5Y3FN@68+xq#34XqERLO<84YOKkRZts-W>H9?di^9Ec@CeY-j~8lna(A@tvP9nq z>4>hldMXeBz;e!1KDV`*=ajWNY!AslbaeO?Z5L;tBRAI8Ot4Ug86xy<7MZW`$B`>a zQE(n?<^Wm1{?K`p>M-pty$~bl*k_^14spy|0hDp<@t*L_z8KIJ$1J)24Ve6##PY*0 zYizPm&XG%ciIFO!oL6|acTe<|>(5a;fY~USD{FYJ6+tw_6O>#3ZPE13XW39=gbwamg!mW57EvKDflPz=wknc%-< zD?bgFKsFcqPi=>LcYKS~E`wNDI@NUC7VB#Fg_!P?`apB3v;RGC|i;6|o!0oQ3V#N}EDz$Ncpk$-rc zna{5ucksyinFsiM(E(V&z=yLu%DoxPwc-2(-0NFIL z!B~x__B86bFzO=+>snWpXkN-*!_!o&u#t)O3e$C%{sW{ll(DaY-#e40hMQNd^x>7U zI##KtYh825%oFX>-FAQb_Rw!$=1AaBE9wn#!bTzO^rLvI_i$tgJ&n_=$Y^9D@qfFe z2wx=4{1cSt1qwLsZC?4IO6ufh{f>^g%-i0YTNKc2e|J*5tfh&BmQBO4K4NeJV)JLv ztyfWu|J)^b1k$2vKaT{uw>liLaEl+@_+tUrA4qL$KJ+&KG+NKyxq;W z)~61UCpSYdibAQm!i2cPmV^LxL6F>H^#8m;qzPvx_BV_ zW){Ae>0ZY=AH$G^%CUsk>$*_QdHcOJo8^eC_v0r7giU|#llT!+;a0+o6|n}KWC1y= z&sms9@X}9rRYrSFD$38cYOP&V{DGk}%(LSfG)fvZ9iq&n`} zoe?eQ4L{sigjO1el%pS5^++gNnu&t)SPFR@?h$&Zgx;=Y%K1lgz^YO8DNSh>v2M_j zdZcw^X>~GCnRv0V>#thzXF#bWK%IW~mCgid(UEKaFKfE12u_Eb!!W3GJTts~(B4I6 zttNjF=>3WOhVr_WdzD!OqMfp+XL)GWd|hmfGXoXSMkD;5kyk3wxFv4YM>!#+(S@`O z@MP)GM|ExI4rLSXFMT=C*F=(55P78xR43egOPeS&gREA&UHlOAxT4n>$`P0moJ-TQnyBXNnaeXKr$q!yw-J}UZc_%rP!A|C`ydZr zRB#6!rruIdZRZIGW2-`95;%V{t=Ik>s8fMhQ-L+`FIB|ye8Ws0E1lZ`4X5#E7f&Q;&!nq`TsB@e ze_x3BBhjbcqPs)BXjEJNiy5ALCX&4xsX_`pS1gST>YOU0FK=w}#?)(U_0Do#B|sBT zpL|4cPd82zo{+f*Z2V6wPD+}dpE_s*8)yKYz*pIkr`Kz~b%K2|Wg`lE17^%KAIDnN z1U8a_JQwJSYu$@JeT=q74DA`Uhq$mbGJe+|Rsyj=zsnB~36K&+yZku6q8B`R(+bBD zS{P!Zf=i2a*Gw4gL0_RldsKuANp)&&~2qx`&eoZpUKewRM4M#o-1yG zkM2t(1dS4ZXL_s)J+w5!O_H~Bp09aK?ONtDCDHt6^zh`P?4>Gj{^j+bO7c_biH!BC z+os89EySYZ@6cH0!6O@59Nvt`P{7rUD#}F}%EK+7nx8l6yj$Qzdg(}~ z1xOq$ks_xN6O%c@pH#<~vXtipt((jRr#FrNALy#0U`wt%+Lbr#4ZdUe-;QVr@%GVB zNdZQGapIiI8Bw^wyl4ug#c@`ESJXa~s zCutyS=SqY`TLi(VG3|-7JYFwy;$!ro_z0Kcs&He#YSxpK*8u~{3g8&y`}>$4oYn1C z=Y6T^rv1F%+qCaR`(V4~s*9_2MR!vl@P?0%?$o>=M?>}aEZqKAkv?m+kTX8$n`$}& zf_Ym=uA5}zvQ^PaQP7%=8u@|}Zhy@91W#u;znIz8|ROr@=p75P%_ z{GQFW2p`XJ`9cJ^?gQ_$&lzcL_APJq0Srb5#%pU%O$GOD)3HJ&XMEkmqKvXS$sVQaItoi+2Wn`I8_dk|$$*VYSP=;B9 z+plR_;!?=N+%Gug1xE=TU55NJtB6dd{M|_&Lpj^levtyWrsVYTzKsb^Ie}?5q1vOX zDJq&2$TM%GW)i9{SgB-h_YZJCc_+*&25u8lLIb{xt~k(Q6D!)c@bcXNCWm!1*7Hn` zDk;tUcyX&iXU{qDu-(IF8&XYKs5VW(G4{~0?7tz8XTi`qH3}^b-zBu&Fy?(*>`jDj zus1Ll3~5NqZgUq(l2-c8$$?^ZubKP>z<`mDRZ?hJz&I=TuqX_PMANN{69rzrN(V@J z^^CWtKCD{5*!Ej`_+1j65ionqX~M&lbt+=TRXkRG*tmy6>@)X`<{e0xfSh=$VC~$C zTC_nj52kyoL01f}j75V3UTvLn9`n_zKI-U)NK0B-3@3N!unJ*XPZ$vCSxe=@2B@u@ zYLXQd^82$BG$UZY?_&^w22a(u${d~H%m&6|@=|WxglyV-mCz#( z{Mz%(e1^@a8nBvwBk2D$tAk$qPpFZTRhHso<1)u8fmV6WUMdcK^3bB6GEC;~@!pet zoH48HFl*S*e<1iiu=rg+BSHqK?M)5sXU)Zj?#OW6ZM;GF88;|=XdHZQ~>WW{#*#y>uNj~oCebAw$13kiuulyoa% zIy=PyFltH9!m+&OBD|E=Z%SYW{=;=Kt#Jhk*f)!0rM{Hj&z{K4>5b%=RV8}+xNbfK<-x~2Qsv^%}#OTk+pqN~%NLE-;41F7oEKqoI9rbfA4QJ=Yn zJ2s!U@5F56$wKw-(&j7kf7xpu2E^5VX>ecSAhlMzMQ7vua9GEG#ILcH{aknRP4}caIZKZ(p{uJW z#9g#_%Dg~rx>ZAeI&N2lOiTO0wVwdP7hUySV?W zcuO2+0Xw${T64QFuFJ~{e{}aRu9o*(rQ;cN|D+hE)lh{Lur;Q9MnNZBRL7Ry!s8mW_4FMC!BRB zXhmHFK9j0KTXSiw4T457&h57hI_{K?xYWT88e!^;&%Y5hFN(OZ+tW>qfIVMtdn)|; z`el$s7Mx5x5kAn6*|7AW4g;oqJdfKR%BZvW*o-FXjkIEKTq^)JEBshCMemqGdxO^x^lIIQIHG!LNvWv-KGaxbfGA!7C_^UdwSi z%8o&1c6xp)ktJXgt3C%VP-p)E${)Oy__4i6dK1#1StKZa|I^yj)k3L1R z^&tH7)8U1B@a~HKr+o9WV!hq}a9u$he-C9qkp2%|N`1Waj^m(Q*_NPWybkD`&?d2Y z*(Rjz=3mJ7*Vb8(h#=^Gieg7V->CJ%@^>MeY3T#zVgn?@tO!2)*Y|@kKN1u9xQL$% zDDGJicq|@JB#pm$Y9&n#&$6lr@Cy*P@_fh;1V*+)io&2W`(O{XDZ3g?IZJG7{oLd0 zi7Np|rn2DgjVBVge4jBqSI#(4wEqY=Ez#=R=pLQsENGvc;nl?(X*TWrEZ22i9r_PR zUAEOvoc;&WFN!Kbbz>I(vYM$$qTF0SfD%iUm&$qs`?2zEY)Mf*B&U#9Q+T?Dv$uS7 zC*Y;$_&nx^`%k=2`KZ`<*r|O0@Y|af;_WFBe#9?T7Ad&sWtnP{AhAXO{i5+y*`pFSl0Lc&+M54EvwJ065^6z=R8wBYu|X1J}Vc4RHWzw<(%NOQ_? z`t)uf?*8;lT;TSQs|R`Ek6+;SM)_Rl1f2on%`dS~RO&o~k-H|3@YMb>&s#Zdw4xyU zqt3WbTDqzgwPcJE_%qzEh8}rEWW7bL`BxM)#%%jKT3fW3-qdJQ&_B7W|{dPF@ zX!TGrFIB=>5mp$Decv0y=KINe`El+NU1^(UZk|bGyOgrgrX=12Dn?`Ff>G!`uGww+ z&{q)e3H?^wA5$n`;9b0KN;8gtqAS>69zaoGb}80Y^Ont``an)*o+GcXJ}Pfi3suvr7MlIkb6Z zGhWT~Ry(<`8!@Yv2p89cx^}E7e?Ze@_`N6}>^z&KTk_j%)t1sy@A0BnMt1lHX&K+WIgaK%xMS{Ru z5qZ<)K>*L#*9hD0T6HqXwdWpPYwF`fhYa`ipF=WQ{u?Nu5HcewVc;QEvhY_S=%>x$2Df+kun^HSqUWjghmLTCZ)aTD%i`NT4$72y z;huFP5kpg;Q~1&nr=O-*+2pTHXd5|u;74AR_BGB7;me`E(E!}F4#9rl;k<{Qk43NP{VuL?Q0_z z)dzCDH?s3(lyKqLz-oR+5f|D3c_z@X$zauC< zDh#!|8qB`9d)AtLT!)t$*Q8!gr6mxQ#`-b5zsHvDZLDLZheb?4A@grDXBy!h!{JfP zRD^(+J1M)H*Q_{{YBF^r>Jh9-#&&fP^^mazw8d(8MZR zOWq2=RxLWID^G`=&A#5AtX@>s{LLHoH<#u}REhppqxFzACbS_|cc|i9XISuo%14R7 zP;Z+|!S0T3kzCQu=^VnJa>H+vw#@Gh7FI(I$-|Kk#Va1kEZ3A?ZWR~qA`z&w_RR~} zRC+eWe&E}E7(>C|O2h26b_Sb|%Tr?VKn+F(2ETs1=w40E-@d_6=V z^e)aVJrQi;3^mvl!c7^>i40@Q?rVFuPyI*mSyz`ct>aDr(ql8U*JkWcU`V@wuGmjL zK3WYTUyqZab6<#S;J6;2EJo3J`3c?AeJFN9kfht$x=V?cs1&ge<%TZ#FLPv(4Gvz@ z&?g)yOqI^b=Bra9xxx#y*>KT)8L9EACx!TFW|a1rM}NwNq9vD|++HbU@$rjEyh$*k zm~uNG0eT@A*R%*hZSxE*C2v^(R5FKHoZ&r6R30ZozN3|pu)FSc6eQH`$Xbq3Grx(pMKkHq)#522h^$uXw0PC}B?W|dcYccddZ%d36S>BSqz~%Bx6h zPSJslB&Qw7VJbF7=D3Z?Fm^DrG3@7i`TYKc=jHKy9PYQ)jF2@)@spG4J~p2_T65kD5em>8j;u-X)nIvI=xd+X2#t!^{K5g zwTWZhl6UY%*mgI@T>OO#D_wLcXJ8aT5vDCV8RVWz9ey5Tal``l|Ip$8NKb)7qXbbU zdJ}cGd)?cZr6J!(qawRPu+rT2F=w`})4s^fg>-e~hG>3NreE2<4yi2fJ3kEEzonf2 zzwqz;eg%p2R_VnNV&oL9h|?e6@C14^rk&qz=F~vvcM@Jvo=`^x@o?8PTx z3>S9AQa%gs%G?8JX_T3_TGso?40FpH?GN*@RRm$atTl5H;bPH@>?&UVA7f*J*@P{d zSR=>04Kcy)@D<(Rs6TR~u&S%sGF1iTpIzLga-dMKj;%2^aeVm=)5YqS;3?vhA;MD+ z3F@XA{k}KnH@t#if|H|I_#bXe>3If-W*YXSmUmp8H%48WB3nkX8G4l|$x8QxPcL27 zbKK}Lxl6wD5N81oyjO+1pJu!>v;qeCtMIR-;a|1y$@86I8wmbB0F0|zt?Ta3XL~i9 ztS?`;R6d2fK+6E8H6HVM;b0U5W8|x=vu~k+gn_N|`=T@5?*I_XqvDfkn!AQiH3Lr* zt-nl$`SU)W(A*MMuNjh9@0P(ZV7i)f(OnIRIs3Y^TOH>c08Aci0oH>s*PEW4X@$RA{9+y5?=i-&#UVrOUh)O8@NbCZswn)Y!$v(eh`&N=@ zj0&mTh`tm_;UZq}+Yd#)3ewrMEeg-Os>}%~57xbox0GSErU^(Q;;~*!r7LdkoF6ai zvHi{if+gz^v1)z?-{;QMj=#dW1fpusalL1yvHMi zgA3C&y}**pN^f_3c=D5-tdbe}Oei+hom<03a;^iQZDRL8Sf&+%dR_OcoV)E@f|DPl zRq^A>%6-J@Bd)cst)^J6H*qoks&B%#?e6~@?IwIsm?qc@Vl?{ATaUjO{6zbz0ImkM z7wu*&)ixyYKU|HJ{v+WB1^W1Z^h9!Em;3mk1)+wdP(YTXEF8^>`FORDuM+rm2Ph?_Hfyvk$=(b^{5>VhIl`Pe3xm>JG$O76(nOy1x=dsdHA z1?MnZ83kO)`;QWmHA91VtlG^*tQOHCpc_|IB)>55!{F!*BusciF6~5oosuJ}PxEXDR>lVz8-b*K|ZJE&I~> z?-DJD8u-`ln)1!u|QG@Bso@GdyytYNI@nwCT>v*1AD3==^Xq4pCP+m|X-Yn;!td=da zl-qjj$=w*cDmVEPB|GEFlL(LuVM}JiPSMwcaHXdjV4T=ml|&wA8DwT0ojma{u(udY z(`6lfX{Sm0zM(taQw2e58^^f6)9WFyt4=>GGP@cGC4tEKKH)KarVJ&qJ zxdb{x|lfG9EAc`lgLhbB7bUPNr^imy(>H z?KigZVV(-}opmmIz5muHyfOE&&<`hQt2tRd1+u8lEBi)E5(rF6T_wbmbDxx4BMhy7`Jxf6yf zkhsJ96oCz|KftI5zjUN1^{dKJ_&1~e@r(-O$P|Wa9QH)WtGT*y^wj~q94rs~%mr0dF_RmSj#P!))#2L4l z%9GWml{?=foix|@81!`a-3UWq<4MF9$z^~mLnKwj?BzT(Cutwue83TRFqF<4_)p1A zFcc2Gf`1*Uc-wlLVK;0k2$w@d&Pm(8+v8-O)s9~o$LNd-Mp$0twCT~O_iq1ywxYnw z{h4yy^pq{;#!$@6)P%_sfU9yMw@p!NDDu7=jO?Onk9-=aLber=Uw0DSKDz%UX=5$;)!SZ2w4io~ z0b`)ZGj`I{5HCr@p`=U$PG9I*YQ|*KLHlPW*w!JlYgRWlsXRWa1>}aERZoZd$Z; zNZ4Yg)3>=8*jyU|w6v%85&px~n)KsBnf3T~Gz&zg_r`vny+tXpD zQ8q50cgSS5og~m@u`|VR*H=#<6brK!?Ws#k{<%46pMHH!4e;amC)xe881pf3yq=e! z$3X_q#8A#9)9u>>0@a?lhXCo=10 zffJ!Y5snr+V4Cq*;=@mWo*5jy>DVnyXfr*J=NVs33$!2qt{H`|JErb8vo7u){8+cw zRsXCQ>%G&zu8D4|M3k7Y`Ef%`$!~^a;QSNB1CLH#aiVqHBi*ZTTbRGXIlorjaAbKS@8{7whm*Z*?({T|WbkUripdXZ`KiaRv*_;?Gl=ql$V~n+ zfhoT^oIsQYaAT-5AscI}D5Yg;^1y;)-`Tn>TFf#*CF?6}Y}K-IqN8x(#wXN;{$Pe? z7-Yb=5V4L)^JlC%kt`8m>cVNXx%2!l#=?WN+82`UIkU8!!_PxP0~~lUTz}t4)M-H2 zqw{pW(<3hEn(3*Q0ZqVf^NQ0#uO$#NS#xq@itO;ck;tLr1YzEPs$jj3U{xRIa?NR> z#Hmu1$}Z8n)CX$|9nv36AhbC`dPZ--{6Do18!@sZ>n_)1!@l?-%f7MKN49Fs#^=p; z%phcm$vGQVo|-GKQLDGhR5DU9XScz<)5<0^!j|A2L+Iz&{sQqva{h7fxN+PSh~zVn z@AoKp`n7*pqSZB|reKI`_*r4`@Q4xX3iqVgALsv?iZWG*(g-1`@s#e9h|+ z+sNv3Lrlsa_rWsj_dJ&SoW0TXmvN;=sJt$!9&3mJ3wnkm16C(LTW*ucVmU5~4S2oRp?z zVJ|3qyrN;IDRWYPf_3GMqlQ$ejnz4IkT@OWj!g_Z(gUH2P%+{r41t#h1C@ZdxR?Cx zI_p*DS8G=l$9rE|ygIxJG#P_W7N+E|P)V7xt~bXpJq?=Dhv;>E)kk7B@ic_UizhDp zJwa-xxOYo+!Z{`ZtnB7K7tDumE+!&;liKHoWZrw-yn)KK-o&?B@+%yV`6Jd(>I~Hq zww1T2>sdy9XOfMCv_VT2X4ZDht%(^@9@wFv@mB-TM0Mm}L|{oLFsf4r#EZEA`P8!lCfYlC5Kkpf9@Q9<(KLrotiQrX z1SWed%zE?tY1VP>>e*TkT9a3>wjVm*Fl)4Jwq)lZMm$yvxj$vA}h&2t&tm4g?XP1xfS@|Qr*Vco+D zjKF&h(Pxg|_Iv*vOlEJorNu?f@$2zS2Z(Rd3-S#$ehsH0jRmgmHwu?z`n;sylVQ>c7lY23}7eeYw-ik zLB-NWJpiC%Xw>OF!#&|2RQXzNXX$OuPqVeDuYVi3IWO)n@QA(qP`lwj;xns(i{Q~-Vs8B_gR z;h&loH|JdG-E=0%_<+ETQijSPt5!d-%ic41Bi#~ywwQ1-d)st?NhXmwn`L?eXkA}= zxlWTGI=$?d3~Um)itTwx7s>v%!M}78$kYSjsZ{T#=b;f0MWY1T>qW}OpApGs2G_j$yC(q`e5-? zYIBdQ&ajHWU+*aEBq71o+wmy@ie~Qwi>s06-?>gBJD8ui*p++J9DhGvQ88LOF24Nq zm~G^d!{Uaygwrv1<9?d}jQ5R0>j`T~?MR~o(Ju_6(~_*u=0wsiF4p^9mreJ+SvPaE zQ$4|mw!z#-vsC@d^EBG@gMebGqEIbDqu%oXcA?*j>Ix(8V0QS)_L#2Ktg(Nt^hQ~- zh-rr*YYGLp4&YNa*OC{N@$Q`F+OzgP=WGjDPr8?rbdy?Nhz6Idb2p5Sxyn4XCUnqP z$GxibZM@4~*Z&pPx~dC;4!MFjJSrkh{Z(cRIQpI|llXmXXvZ&lPK^unnmw0(C2DWb+QJXj zScX2Pn2+q2G#qXs4d;7V#kE-rs(^YED@Yl$qbtu~es=^T{m9IL{C7@PJ`Ci+%HwMh zHzXsEX07Y!BHv4hn1NcN2bg>Oj&?H>3>~TnROjIx9l?(g@60TpARk=#K+0~Q0RnzL zLwu}fMZ1R10ZT*nW|4!5E{#0BW!LE)vPtstZ}xBd)p*DIJfF?xxf+SZ#_fn9kWR>E zUKE6=0-8_e9oM8@7C#lFY4RvzHh{jJV~qj5F6+^>X734?-YAG-FzUW+nW7OstzI$K z&$>GrGHT8RHK~S2dGj@eUveD$e$JT&=?(Fu@5-$|%do*9j`ixcOfk>#Lc_~vac|jc zy|j7kMA_*D@+G6?n+1KP~~xK+&A>G&cj(#C@D>JqQ&doGYg6))4F&3t3$@=Kwj&#u>>3V3Vj<=6jM z{$Er|fcah#`oPm_)dZ-r=F#56;jcTky}^@iH947Vrj-1Ur@$LASq82)n?9XH{#_32 ziYne^S?QzL2`H=U%uE7LoDz#!}0m!`)+%^ii|_u%grOy+4tekGv4e50=}U zhOL0od5@MVPK)8BSL13lz>->_EQtbjh^qF-hS7q(~ zlemP*nfU3lcPjUlt%VEi<%Ha`*j$g4uFh_|!}?p7%siwXaHNvA=EY-&sJq6cUl9?9 zW=?qPcOz_04RV^Ssg9>@x3N=QZfgR>#P!*a7q?6fC0;x{*J=u4DJd+9rWk8Re8^Qn zK!TttdlsowM)iij2Q!oCv=bF z-f$(*5PRTDpa5BAPKodG^W>PkmS_4$ePo7CS`pOT0XLoJ`VTxXm?18JKNt0A3!{|xTwk#P5Wi4AP-w` z^qsPU{n_V{WCGyZ@MYRNGMjQlHi{b1fHe5d3N#oVW49<7CRc;}p1V_>lIJ&O=-0{8 zz*rdj2zG|=^mWTfA&5HYG&cZD;eDN>kQsmFN(#OQf~)=qvu%Ey^|J>GA}Ga_kB%kW zCHYKKLz(H?^EB@A<670!!=BpukkW_Q(ICSA8fUj)KRio1;vg`yWk$ye&@`Px3rAFk zod~wf7}A7tgm<17das+6TtB&8Hcl#K|4yyr*+<_=x#=jo4i^LuH?OW8Fu=Dr^z27r79m-I>_kTn_~OK=8s@fxSarG+fJnc||SJlWRwE88vq zI_b-btwo1+mfy_Jl3RcWnOx9}I^SnkL0epu4nvI|MVEAKp>}ay4maO#YuRoSVc1y8 z%nGm;LZ1VeEvqpt<$Gt8PQrg_CHWqCj9PypbVR=cmfuOb!74r&=-|k#NNZ`A7H}W% zmo^6rzbCriGzN%4f1D~Lw$j!Anuxj&-l6oqOIA__4Bup_cb>laLe^z;)b3<`8Z`93 z&S)^@DHdUQ9COdnW87yIcZF=L#QJGtM#{vZW&Y~dj|Njt&;%Bef}xS7Q5Go?r=_dY zQ8S~)e>VJ_WxJNWZpN8aSG@56m4`oek1WgXRxMpf*T=v4Y0gb#W0G)t?_O=fWiMz- zP=hOk1w>UP@loBifMn-b74U~(a6YnoOHa^i1G=Ui@gOicAZ-?UBa31_42gVm#O^i@ zPk?^TSJLz>HcjSJ`T^nH`HvAr|3$o!1#udVgp!1|wVZ*}+yJ6%XP?wI3bGM-;%`lu zq&}|FYYLQKKJgIxxOZ}|+OhX`KV6ADS3`WafZM=Ad@`B&Aq4lh&!JnLYd?2s=kR{7 zZ7@E4i+2rRZmALj5iZqxG^bCmbO!#<8`p7rK_F+!3VnvIpNoe)b&uB@t?72X-n!hi zSf`5J$=R+MpM+EUI|23&?X6Fe)HqKVZ*n=%ytTmfIX@n4BKYL!!B{NRjSq2Hgsau+ zWp13`8EuvC+h05ae{;of{$?E5=J|#fPkJ)B8C<8(F<%k7)gQ~Kn3D9!rm->Kj zl!HeX=)#j@sUZZG#f&JE%)t8IK6t-s1_d0!3LBcJW($N4^jJ<6M%##ST7F+UbVGD7 zFQgAab8Wa~)CClJq2gh}yo0Pj3mnd|BXus`7l|Xu#=_c1B!^{+>-$B= zymL;b^g`uvW!Hiy?U`3yNhafz{3zu#jwXbfZ+7(_4bf(vNdaUOiBhQ+atx2jSr5&IzM z4xZ7Ul))hdZ9hB}@D-vNoe#J^N&AL-(VaYxUWm8SCRsmCW~D_^`Wj9j2zyq6JRi8M ze4b^q_cF&CQm+0tT^H99#s2y}H5b|a@4{t#AoQbU3Qwoir5_KK`=!Qw>V7klLxX`{ zEnKAiw~RUbi+e*fuZn-O0e=&H(L1nHJmOKmt~g0)l}NLeI<7Rvx&8?il|zO{P7t_j z)9r2rJANS?tuBAO39Kl{nC*YP@7bf_)gVmN{lIoF_kef82;*G{=Bx1%yn;Y;G5o?% z6@x_uk;HK);3n))E_3|p^Px66faWIn?S@1X!~w~U1Ki3}`P#zTAN;$g=oe_-H>0YU zo%y`qFWq-6O!@ezyPj$RmbxCAPh4>6;WZ<6zk&BLiKVn5xJRMu6=Iy%{BIq_?x*2M zJ;9RU=2;Zc+7e}(595e^TVd~}9fFlA*)IfR$LWS}Yhm1BQOSB&fT-=b<(K2o!yhy^ zeXk|Ak1?*of3D-Xwn)WtLJ=`n{6AxNPuhVBb6&!u8;Ub+(EFX@=pF(EOXe88@60qhXnH5fvsFQbqirmmaYv&m9pTK{YNym_78M;Y^a zP)$MFmZm%Q%*?+x=+d*|Rh}KG#7leH3YKuW7oumM(KP5Tf04Prod0p>Y0ps?3;NF= zOBIy%23DDKo>v3=K=i#7+m8@;b5OYfGCRzX&#b0az z0VKx0(_8RDYM{P--qHmu#YJ>={=~EOHzHg(~1yf7JUH&ou2ix0LP-c)xwGrWrCXRYN!GgMM4hUXY*zscAIN03s5Y z(mBn#7X`Kk-&&US%0HO94U>wKC&b5};sB!N;yeJYblFc^aVeg11ltvru0;ksQK$y2 zA3TU}j#*JUlOjC%!r8%gXZJff03O?Go|$7<#oX>p$|?w)J$2aAO*y`w9>aJe5uLv< zD~Td@F}C)CY!+lI1|Q5Ft#{2p#^df>b!m;sJBi~FYBqhycX2p0er>$rrvZ6MvrZ-G zP)T?|Ps@=`r99s$ZqrSeX!^#l!3AXPw>Xi_>G~4tTk;|=Mx5L3tUQ-M;f4A{zRy}= z6@|M?pLZ^f#vOkXpw+s2^NI%XdpvuY61r!;qX}K?NZJsQ;<&E~V(%|R5oaKj>fFH- ze%pSuPY;qZp|3@=q=gxu&dAaorM8fsB$`g#e43>1-F{u9#S$jP?rFXG%Pd9wBDscm zYLh^m67z^OB*|Zru8700bHq*f$1pm16Nut5v5$fwvFabSI0on_PAfgWG?|$I*OPgcQ`?|+ca=W0 z7dM>>c*Z!!c$F38VBR_7kEt#~gZ7Ov%6&8jgPkDY^kZplEZW!#+&uSTQ?lMXQq;(E zEW~-;`m)9-4df|a1mxp4Z??Y8yEiKnU?9~H-V;2f*MdFDy$xb-ifiNcucwSkkHYoV zXiCuN^dFMiO)^@@pU&LIuihsZw&Tj@YR&%oB#Q)VL?H4JGPY|`Li0XnGZd@?v?K&w zr?95t^I%i{?sqIS*9&}ZCop7x_AEtg0;n*4*8k63`YBZypRd%e_fIs^uj6K)r--xmvc|QYS>@_b!pSBo*+HvpRu8vTe62(i2bT zhFD!NeeGWJTPq+jJ!+MTtb+wdw8WerUUCjpGL)G;cFTs-{m%l@XwIv6D{@Df{AOzE zQPBZ4iB{C+yr=KqT^`M+lj4}5hHlz2jA}2sG1}-cRR>|5xFF1HeL+x(N;Puxe!J4< zgK`fPz+=1E%MF5+hg52O6ZyjnUk(5pMd8QVew{Sa<)ygb{~iwbcVYkm!Zq6Wz6@rl z94jUpX12(J@=_B%KXU}G>Q6}T=EonsD{^&&r&K=QVqHk%owdCJ87&6P8;YBi^35B?bDWgaY7(Az`srYP<1ySkkNHgr>^c4tN+SIg;x^hG&z$(GTk z_^Y)%bOL78d_vUV`P2a(NSx8T&Ik9g0u2a^Mw(B*Woy(fs=FHaC;GKoL{G?Gna$lv zgNG!8C5P=;jQ}70SgD+kQFMKoZsL7{UgFD8` z9EB-_qVDnZ%K56Bz}-e~F;F&iuc+&0xMc-nCKN|RYNFMQJve3@;R%~9vQMIbbdtK>4{!5H3u7$;eiC(5f>n`cWQjbV zV89-sL8Q(hT9R1E7XC>!jc?j^!S*_wzO*oBcA1^cGV&W$|JMH>|4jHzVL&S3mjX$6 zx@`$;!6%mVt;mL4q8-o$qnDZ`uzM}yL=vGGI_OfiGo9@iQQ2fIm7@1e&ZamIFB7x? zQN5qnlKYOz;l&qx85`yylz1K2q_k=)j|PPQ!j;wMDMMdeY{kMuuCV|XeOEW8B-<9l zCP$r~7)f2D&02*z%n?9)NM@3pJTU4aN$|+R$Sz^rPK3*QsUKT>^;OGUK+@ZsT*k+aEi$`e?{_Ji@;{0`C1F7US%@NiCXdA>E%!QSkE{aefpp0Fv~ zs*O4j4Mf@KO^rW&0+bxXO5>& z-ERXMvFtX4YH`1>uI!P3g$^{GyiZk(r*Ib5-x;^Kba`B9IR767*TzR~{}zJ4gk~HQ z{!|<|+K^&*5|*rbXk+w6r@e_Qvm|#0YHmqGU^%)t<{W$0Hi@Qd(%B5XYBN#CBLj*P zX_{uat%$!3g9bkT5pAy}SQe;Cl z9PSRDtZ+=prbAn~lgOK{!w1>zzX{#jml$#aW*hth`UPNwam~vDNgI0U6HKV!h`o}j z3r%BXCIv+5{ z9S$Y6`WiiGUT5)V?&}^%3|4s{vWw}mluKsVCUH#yLihhVt$v}wV!9ZC9=ullc{Onz z#juq=PO({Qxs0o#L z;6%+4Do@5lzjgt(`~hXYtCGd%vR@2<*m$TYraJ1aY#7WspuIG<nYXkeO^Ef1_J~>669(6j}Nwt z1~J{tIRD4wb%xSw!W9jV|9uNvDL;4fG=X-#RO-}O&-a0{U$Aclu)Srk9RdsQv4nnG zS|y+fQEp90XyGzVyq|4!BA}e6rw)AUY$!2vx{u0wy?)+By?u+Qe(H^B`9zE9VTr;* zpwg|9EXTq}C8l>pcP``T%OiBlDN)?%^kDxh>PNHGq&9@&tMZVObaQ^NH1FdnwY&0I zi=l_OS}L2(&0sh_ClaMfP0*6??!N>^SESJC@biiAI?M94pPhB8(un%h>Ay(TKqar) z^m2N|Da?ksXX&d+v=MtBvnKTolLwj>-@G^3D!*(&(=i|)?=H6Z;DSil{QJOKcD0K( zob{#5;TGJYJ^oF68ejStN+iHMuWi!^a0?=8(C^SH4}4MC5vQAe14I+K3?nxayFnO} z^Kv$QhAoKVf0_&^jG`m zTQ;b|-4Tr%HH7NB(j+FM+#+qq(OB!S##tt{x_(cj-n%F*5SR6Pzu=;&W~`tBmJkG5 z?i5f??7(5y{Bpy;09+qWD)mqM0CQieJzSje$m1&f#yVE+@4_fSEwXp({9rS}=DFP# zDsR#D(KaWH7w?DAAamdw=w1B$YFVf!x0UHUae)CwSbRU4GRo$$+&4v7KzZjVPtO2K z`UhxLA7@ZZ?pLVuRnZjy+dFyccFc)DZrf{kr{4rk6{t4;NGD)ad>g!QQuu8sSJfUB zeqE^B>SAofeX>?8X15HC_dh1zq9X*SlX;(kt2_X^o*v=Sd5J^yZYlVuaq28LCZDN7 zL0gCU3luk8@prpDQ^8eSq97Fe&^d)k+;+1|$glh!_ec1OrM<0b6G(79=ifqb#*M06^tv0Rp&oqt*`nD7qjfc!wd3yan-@UTqRg-A~g`1rlM~29aKdTh&Q#(fk~bK z9d>aZ(E&?yn7+W1_7rlRSRUrg@@|P16Fj;iJ{(Z;VXkG3@Q`KRH{L+&uxLk*3;~(k zHowmoqrW3e6y7Mtq90Se7UwM+jA1)FrK@i?FiKTz(GLQVncZB&mhxI*5lBi7K z7ZYV(Cuf6*yms-Q0>E3D0UT9Xj5S=Gw%MDR?BcrFTYepyr@t@Oa$J3W4@ZioDBi35+@e$Bf-MBLYL!!L7ljJ}v zTCf3gfD}`Eu)>QjT9O1vtaTjtXxxU)- zDrmO5)zVHXF<&qL=lxm#A3SxE{`kMn^uQ9ndVRa_3?Bs!#wCv*kWEJ|mln}2>Xa4} zVN}C|i11ZPiVr~6eNCiu75XiTzMC~+`-360a(#&fU;X8=(e(vhbS;HdC=2_-&!w6j zWP`lQCHASqYc&lq;YHNq9Sc_J>LSj%*9VsIoZPtKlJ?Xvzab#x;2Kyxb-(!e!-nYX zrRqxqIaz;wBvymVk2ZG+*C32r@-6BlyW$8x9^U5se>t(qmPZA^0<%simUYBTZ;ujqK0 zE>H4ZwlD%*L4fu(BYdWK#71z461-qV6-4f=Qgi>a>4+Tfl-x- z0{%)@A$>l%_z#nzE`&d(sMMY}#6p^mf;>_0$2_=h^`r(Hth}f)F)zwZiZ7>Dr2fP5nlgD{hS`4m#pv zk)hhdNYd-eoO$uke_6k2+gt;HZt_&-8DH_G#ckfn z!pigyiZarqcEB;s4F|-j44=OF(^+{%5uNAWQ7ckV98$=UpF{ zAA5up@4k6$qs5fb8iUhp$EKEbYrZeK>v6w7fLEs$dTr*JuWvn7RFN;*V)^b1avRK1 zobp1?q72+ycrISxRE<{zDY<74&4}k*>#RHhHP$ZF<73Z$#PM_f~|9D&FkIfc?bVNJn*XWpug77H` z{AekK<^PGK5n{94MDkxoGx*n$p#DS?04#KP7q8gSvKwRFHkB_6e_FPGT$--lf?n^x z+gGNDc?l7uZ}Av!l(MqYG@!!Z!27(na{sMU2Lm$nm;LF%kzHoqUfz&-bk?5P)655l z=WYc7|M?RUHqyqGrGVCr?O~mBG8;tdU+I6$JD(X>vq(R3UzlS*el=&?{lAuUWs0p` zIW^eBpZ;*?N^zF)$HHtN9GFyR$vN?1kXj`cxjLYXDzyzcxWJai(KmSu$j=vz% znaOC3(qsW6KaaY6i69q*8b>}oj>g9QqcXvB%vV^dWws5MCS>x(w=^whmj!p{w#pFE z=fOzK7(UsOo9!<75 zMU~NHSh9P7h}4*gOr=cQ=+)tTqtyz8nyZkpdV?j;Jdc(edusln8Tpc)+^2mh$)1q0 zpmPB(ef;t|#$v5saXm-Tggo3z7CFZnSzoRJuAsxZFIY@G6}(8KZ-m|y@RTltpXms3 zzrIL&wCEkl(LYOhWhoIr^?LZqf5Pq(`z`)p3(`O>u5;u3F1Uq!U^4fBxy%8FAMhK( z2tyE)wimrP`xg`_1tq)N`{ zkd)vHrVE-=DwrbPC<*fEowX6&rrpJ5+Or%smG@?+hkfTK6y@BP>rYaFq9gy#tP@-| zP0ORdrlITOb7{H*D309w2J241m4M`qx!@HR|5qFE!T*|0Er4z4!ekVLb9}|9D(iID zO>b_V;!-u`Zim^y=}gAxU5pR{i{Ci11&}Yj2c;iKC&kJ+bySK2SmP^Chu5N zi_uyxQu3CuIeFa4)%~bF=+oC)rKx$Pro)exOiAoR-()ay@xK8RN_N#Vy)I6wePAIm zto~lPkO6a~fq?YhL}+|heUEwPn-iC(pY{gO?!*AWZH4=+y)zHjmfGJp5r6hloLXF z6-e#VjoMqRa?QqH8BgBW7_`3CO}qU#A+;fZkpvP3ksiJM{dn|$;kQ<==fIlA$a*7} zvXZO!Z%Wp@c~;T>FKaC7F|WTcfdvgFC|E_*CL1?LFQaOvM?d7X3mGY-xme%utL1;qqK)c*+K?G?y4xyOU+o^2+{k&HHyKj&^lS>g&NLG8u`*#jkcrp%;qP7Ko4?X zB)|a@A`@y)tI-I3vh`7VeQH7c^gyT7Ff@G&V+`hccQ*}2ziXx`UKtg-wzNg+z=msY zHuY%T3{#t^d-g$BsR;()pmScgJ)9}i-tKqwk`-*F1==&Y|PWi~U8OW<(ylrBLV;rT3(dQUA@2$Kxwk;t^aj5?x z(On3BJ;~Z+7f0}FMk9yyTg{t}6lj#14TrSVG4$o|^WQIuP&`gw7hww*kkqvIP2taW>@itZW2Xv-i8dJ(RcQLAqy zP7kBLE$W{j5NRu0jk>EM*w6u79Te-zZL_XcL5(y;9P*Op{)X0S9XiDMwX)Fo5RLk5 z*~7K|Pa5C&My(TS)>1RvmHYKy!_A1Ztck&`<+_cp@$M44i3*Ab(h0%(JJ_f}21g#) zf!ltO6EiEHapQ#8UH@IEvVPTV`&T5O71kfoHK9U}T^Dy&@e+Mz+xhyQ6J}!rL+ZSD zGS@k$e1A)}BpO``({oO6*Q5{EvafZ1O^V-F+VdcN-?w7vaEH_C_a&C1RNXYa3pI;_ z4Qp#e{&;TrIq>JAp9B`g$J zfJhS2X%DzhnCDuBP0ZWd0yg1m5~_~f>3(*Y8?FLqMpp3ooy;aiOt+2iUt`+)rU5S^dv1gigC&K78Cz1s$+jYugPC^@AQcUMN9_kCV zua2nG`pu6*rVt;#Nna(9^v)ry>QleULSC9d89jN*p2TzEgj?{qR%CBg&tjgAoEwQ2 zgQlLq2+_1)o{{dKy_0&Yx`6U-o z`HhN@Npr`;QwfcFL>w<-BC5398vYu}t2y6t-h}zm@vxcbSX_moJT48t|NkTE+~b-2 z|Nrk0%4wxUa_FRbS5C=!BdK(x^TA+ES>LHK#LK?VMnNKv&@N0<@!Bo$ zgl;a9x;(!}2l@R3FNFRaA3Aa?0jZG8%%)Q%UNmKJNaNjzVnn?ehYj5Y!H9VZgnqKj zvzYQ`M{6cxUdi&1Jo0z%Lr1aGn94Z9w;J2FMFF@Ghzz&K;%=KDUXHJRo-A+5&5w6H z#x}OP6?Dtt@)-B^qTfaTNkb~BS0y)*?oHS5N}en46F0xtkLKO4$tWD1xslsgUh|+m z0!Q18wWgnMU7ByCSN~-E$0yi!>ClkR>q!Yu4VOe%>paTuET=ga;7foV&f<6f0+~Qn z;DNTm+Tw9K!(SgJg|=R8pA4zu}n6C89$)%uF!Z!H#siZsa%tCbAJIBr<#b4rF)U zP&8HF`tg#A5SJA!Um8w(k>eEjw%{BO&8wItRQebK{qPy zaQBf5H5@zpHLNU_cozj2UNJ^U=QOU27zZ~bFpteB&eZ9&2YR;l4M-RCa&^g9^V8s< zWWlS`Vh=EvgY17yi78&P(+C4+39oxywR22X4;&dpw5ob-jdH+VXC6`C9Mz>GO;%V<;tqYtgta~Vo4I(!5a||X%H=zP2?Ftd6ndiBaf_u0>QiXl3 ztLhhsXYFm(0__%&lICQgOZ_YvbH~G-^N5E`+`V>tm;)LUdL_TZrLt|A{g^IxlcqItP@LTIRz?S zH-<$i6D5g^5VSA#(osim=HZm77-_rMgC?Fjg{H+3YOt=<#yv=;U6MTBy_ee&mLys) zoLFIOkwc8)<|=ATm{@RSyX~f9-rEh` zn$P5d;_=NH;DQ8Yw_{`UOXAPM0R(X?ZO_bIAy&YgYN`+6qlOxG`oRqui;{Nuzekv# zvci3YP9Bi@%G+{S&t7;Bp6d7n8Eg28QD;wM2Of>N84LLr_FTHdHZbPyKr!mmc?Hp~ zdz5qGoV{~PhlBR5G$dOEWk;%ksNa~~R)&T;6Ad>zg{J|h8PnC^zZPUwvfAYJqjujp z0d{7)s0peFe*&~?)Kk+@gML5xFzl^th7j41{>Wxd%40rPDZ-Z1cfwGivvvZcT`7q+ zt2^qjYS-}0D2}AgPzT6*NDZZ;JxO1$fDs03|51cZUSX{6P39jO_16sutj0~C zWmPYpSSz_rn*9g;Sh6D$buc|zgC+fTOry5kU|!+aa*{CP zP(&{Te{&c+7xNrhYO~VlImF|p)w~dw|7{;lylo|Kdf}j%V6BiP7K9#}uw|jRhs^%t zziH>t(ymWf{MVOao6^di(ZmWNqJOc3k3763*iR*MWL;8S@i@8u8ILjiLwV_t&+dmM zNc}kiV96L$A}#>)WN7^OW~8OWmq5*xOwbMsN$*cyjqZ0+0?+hb<&!VN%vPe4R>mtz zrJ+%x20vM091-&{agOs$pE4o68m=5dFxIpptUJ(JTRIxR zyAE^pX>hugGfS^-ioMLWTkNp!SxIarV~)~Fptdx(vf0ITEy~w2VQeJMA zW?sc#yBDiJgePCR@Hp0#&@e+SQen)3^*vKFVeDBJplo;}{TJx8zGvv0i{hFpy;aZU zBh(}Xk2A!*TRrM7s7IvnSM@FD@BbR#O8XmMJ3GPK-V+U`*WKtS|9}R#4ks$xa)EUp zTaqUP>#jrJiw#rcOcSrjVRMx=8)APXZ_G|HZQX0-g03G1Ra(OVD+(9oS4DzV`+EEn}o{)Y5Vgq%hej>P!%d1#A^%N6zefPg!sP zb^9;JY|Sq6urLdb5B+4-pWb&dk!mpJW8u|mNA}fkvCG)3Sf8|9XPW%BW}=(36B%OI zn1?13xvhrP(dQSY-JHe^ob0LKJaJD`&e}rVp1EV|7#aOD!!}KNjk#J(fpqZ9@SY7p z7A1Ke6Ofjbqe^;-1W_ykaHsVggS~ZL)ej+0)bRr<@hqAQyI1Ml*GV-eA$T_WQD*UF z5+nj9JICy7(nuhKChcC)%UJFkh5rN?!?eH7`rVR#q(sEAvz{aez37_@{DbT@*4Oyc zc>NxOJlJ)rJazTVe>h(!R;fn2&o{#awEzbNGGRE`u9eW85CbqzqT34#oy`&l!-Pe@ z#wQF3a9a|KKA(31H(8Fr&QX>ezPImDmiRZ}oZ;Jf<*s};YFq9AWLRa4-^X7rur0E! zVYCR~CotPecc9`6$L7&Hu)*_?w>9Q>1-@qD$`gAv_>PSUS3rzzuYsg&U5W!DZwms? zQ4qjAP`>Wm=Tf^yNN?y>Qss*x=f3oEGhcp z*82+O^Kv26!izr)AHvn?3wpiC4_$9spt~nu#F>5zh%yXPu0V59SRTE7X6N#T#Q-I< zh_z~#jk9Jwyddb@ho%qQ#+dnOjt3? zp=NN363L5$$8j4@MI(Bf+Gj-ADN-T?zXxB=qN7Q&#Cls^uWS z!G>GWATLw1NSb7RZ}0P!ISe$jUn>B+?_PYAFfJ@i_OvLbtlWj{75-*<@B~SfK>s%( z;Js;sFD}VgNSid1-43>`yIHJQXQmx0GqB8ADYq;K{knZG>EGx@0Wrx+UQ@6A>bK}N zY$1m}r+8>aGt~X1>!{>3&#V~gpIlQM&ugziI6srL;ss>20O$v+RS$$DnpOLRVJ&eR z_2R+Z8%T$_xei6?_)-C?h5J=pF+~)yFgWpV)}bbAB*i3B}E8K0%*)Z=4BF*m*61r8@S zO0)k_IhTS1!B^jH-7oEq;~6mOgC{KRm8;C}o;=@D3bqW-(Vm&IEiD<*W)TM%sT=ar z37+iuYV|id@1<|vXtpZCBLOsyHp>>dS)4kBULVCfn=Z$amzTB~KE4SK z!^x#&w>{Ih{3NOo?$J+Q&~jtKsG?s=vbljWFm9(;*MeOI55nIsj%D* zZsF+lp235=8A|GEY?E;QM|z@y!(_j}LuZ~@59WIPL+73Rn;}F*_&kG_wc4`NZU<#i zRo0rYGG$^veOsILKv*GIbb*&Avw36IiZYu&h_d~AX` zpc{R>nW*E#d4jCM+sK<*dR5?qCswr$>|83`tXJO36__9IyS1CK_)Vs6^ReJJoJ53NR09o!PivKav3}y@`c`CFw61oB?&NaL+)?3MJ z2U&jQQnh<(RqBr=yx{fyO_KQr$a~8rO6b9P*VMPf&rP|1OYC9lc6l$3tEacU1x|Pp z@Bhd8B^(o_v5Rt%yjzc@*d6e_pkgnx7N>GW|?$f;D~t?JuVgBF=@6)FRi%tF1mT`XRzL=a&^*oMtoCY zZN}|V-n6vnX$(L@OJA9OT6=2Q(b-Ur-~Pt1TmU!}(9m43u?(xnkM_MtioHUJ`p3|f zjT%jJ5EwfZ?TSJEOh<#Im06GYGx5*nWIHtrd_Dcog@vbit^`72?q`8L@xv+i5y8N* zMS@1foSvyh`Qx69ha^v4P80JRzUI-AFlP6S!0;nokm4<@S*Vk{Vna0(03u$tzIWwB ziQFnx4;dT0=NlIH@o<2*OrfCu4*1C82Xraq29*+d{$Yg-HIYMwiY4Z4zx`|d<~*Np zr*kh8*DDxpK54$Wb(RAivpkG_Hy6+2V2lRfqlVraVtzNtUKn}MU%vzX)zWy=RNy|8 zDbq^c6jO4BG*;QA>q>!-4LS@*!3=s|t;MnTPgrsP`6pG{m4WWZSNZ5V(x=x3f%BfX z4fZgW&P|X7tOexlwYfi<)<;w`DP?zV19QkZE4=i^`~GpGIvZgbZ>a8I;#(w?_-u~ z;%yeI#cE7Vl}5!HZ}fw*iFwsusVwM| z25Ro}-DMRYdj-Vt7ukS0*YmK`KeL17^-Y8U$N*($v>Z)|F`u$%zAHn$RZU=z%>f$z zV>oWg{UMINYY>fu+Z>)qHR7gjpFG`PH@?!Y?1=Va>%#BjRl z(-*$ltwb;1YYuCyn;_3L>6YBp)F2tjcjymQ2qE^zJj-sV>rz8MghEW(O|8P4KrRb)&Oc-%uRB}OYY7VjM26&6(1gs1h;Q^! zogPLc8Nd11WhpwJTRt`z1!O`!&eDiNab5J8H}82Q8;<>5@i6J8FZewkfPc3XUf26J z`l5Nf6w{&9fo--i*b1$wQZ(CJsaa3_+zg%d#h+VjJdU*dSU+Z`UVL`q_UX}wLi({W z=vi-`=A6nR;K2Nxs*#s%;gPl2_9goaj+2`G9znDS8##G$Xf9bbm^!j^D3iO9aPjw& z!=ljlS$#|^9n0$Fyqn_^b(_iBr+l z=za84q<~Fak7K&MHOH=0B!~~+TNi*9ITNs;M%PJ1iPnCM@!fXk+(I~t^Ym$Hs z2|{|IQ|}PM?1%K$G1w;7y;o6_Q!)#db}f!)mugVmE*rV2I%tmF-&Qn_wxj!II(p=r z>dZu|!y=kv3VB__;3xtyKXAQ}Rp*%AUdM7LDff(2ITSPEXqlWbTH)g{ABVMfc;xFz zIdUs2B_cMYq4Gmu{^dXiY*KZ>=9c?UFPo4iS^Utc@`w7hhXOXx^0>B{la@?k7&XD8 zcMRH2&gW6ZA}PNAt(k_^`>E(&UJC4{Gv*~6S<0@#HBp$Ve!tSn?akm=V0`Gd)+Fz( zKm9M*Q|AXk#KIg-s)MU(PvDsSpTk~SIPcr){{-|T{gDL+F8KTNs<^ov!Y1(V3!~YN z0kros3#JbpU!T;+f^l52ELz=T{!rh}|K^h5kD<1E^W(oV3u6Qh+`+5F+sZ&aFBLMl zYSTBXuL4fi5=rO$+%JYz7aP4a-@rxtp&&U7wmoEsCU%D!aKRDl`-}O{Gy0_@!AmOyoWJ%cNe*kJgla zjkjb5`I$6C%APsWFRs1^Qx^1VD7?wlc8q4WFln|ais-M*dMXuSY(nQ>?!;Tr+Ai1L zX|hM182Hxgpho)%kVe?k_CDr3hj#PshS}3QhOpsahf^N&&kr0e$fi6U9M~7Lzvc$3 z)+uMi0300_Y{WU~5T(`fLH{?+CppboM+ET$Pe8Y<^jYI#rHgRMqk`(OzH2E_y*%uk zFvmAF$wD!NS!IRyM{s-`g^QLT%|@^3RVI<|qM?Gp)p(y;G3TU$Z$3g25pH&;`@8lc z1O#pT-A04tnpe!9`%4UmAEBcIJ%mBq!G9%K4f}f(%lu6B@}Dv4h7G+|zNOq!%HHW! zv_Z|*F-f`O>4u#=VIMG8$I4@F9;1z@6bd@S14YlSY6M>XL*4bnjz*6?0_EFmNYj8G z{dRAIN|{b|m7o6SHpN?8@8Nk*9sV2IIuUw=Z{L8PJBSmDWrIX#uZHsXOjZGI9%h}< z^Jb1ZMDN_5H+b`3zv~avEJ`f4328CG){R*va~wZvV-^6cOT*qjf#2m0ysG@IIVF#N=f@$uwbt>oJh%BxA2en;_y85q^2{=k+ z99mOrNj10_O+1{)3ob2UV~&g05DXc#S$y^1)p-4X3roYdXKddH+ID_x-J%$S;ZcC; zX7H=S0|%f|OQW=>TUp_78v~T^h^GrKXBiv4tzoMeQ>vIl! z4RXqZa1EkS{DKOCZL8XqGNLkCOQ$0Y&4GJsV2Rr?WmN||LwC$;EL3}5PIpl^jk^eM zzc@BFS5NAPj9D$eYN!=9(=FB&P`wlR#^AyF0mrItC|6*)=4P;}4jIY7^j0kfv{bSW z0mqYN8{B%xRI|ZMKM_HY>S4ZX@>JHc_1K$F-C2Lr=IgDU*m~n!X_*9!VcxixaGZ2u zGF_bQoqs=NNwp*aG22-Ag%fN4X*=KiJNJ!s8YtHBm{SGBNIoR`C2|@+pC;ZPc8(*N z5EW_TmD*oK5O)1kL)F`=Jn*G&SWT}79J*-~K~!tg0TJlzNRxWq%k^FA0W*$n+&5!! zzB;jI6q#CCMn##Aj(ygbeV&i)5|`r838$;Zy)odb7-Moh&MHO;0Hya{IKo8GPbUz^ zsv&3)(lp!)Fy%Box9{wUT}kr8GAu}#6ykdAU3vA^OFa`8Gae^ItTAf?K=%R~Z^NId z(P#ICFEwG8JS4T`8^?L)$`!bg-=@4BOOI@)m47vK7h9HBOn6;Us;S|Z3i_g?b2gZH zk!M;7lXJ{w#!t;DV_C~KiAisMIDr_(hv!~*4efwUSOt7}j3gopIfn6QW!9rrWB-<~ zm=D6GNEq4$1N_-FO|m5ee3|llH#h3+rlOshVmR)*Pq!1bk}i}J`p6j-*!CU4cR@3^ zTpU!zVAyfCF|-HkkNu+;_^jG;+<#MXJb?HH?Y|jRlZ6qm>IO~aYRiAsoi3lg zGx+_<@bPlAqiGvV97Fr$!c`A52K?QUvv|9GZoHIDF(!wlOe08ftgQ4zP#1$Mz7Y|@{W zbZ9;M?~BrbY42?NCk;i9;qqn0@uc0Y4W|&+`FTP~eXSw!cuC=72MfK-Ym;}J!Mk)g zW84i-5Q|CpD#ra;Q$g&~%HDP7x6?6Sz1BJk|L@v`04D@C^oiM$UFmjdmKo=dU>zjA zrR988mXVP3iSwnKPZX;%RdjOQanDHZ#m8@ImNnQ7@Hpn_TO%~zs-_O!mVSC)xM6;K zxovmsUQN9Jvy3D}cL|{^%{W~gX(%4CTX-W;$S|5XA2gPR^~Tl3u@2KWu~~_ADt>!- zPr&PDTAIJkTK7adeGG`#B!3}B`L0p5@(d^Wsy?4g+&ka$BV;&(8Wz`akb@?reO4l> z_ECE51P;X~h1!VXtw@T%VGH)Be-Q33kih*;FLxK~XLUNNH;hF z?3=iKx<;dqhjUK#&o|xPHs!$dF);Hhhq-zw-qP%I^2IjW=^mBwqOZn(-`;LF_E9Nw zB=Uu3@P>Am+PrAZ|2SH|;QX=qUvsVn!OsUS(USuuCy2aP{J_(^5t!p2q%UX!`(Q3a1rl*Dt02mhc}WIx-cupSQhs4)qnwB}5h9 z$SdV-O3Qz*EFRA>M%O}R*Sef+_8E6lVVq2$NwDR1KCe(zSihcL+Vd+C#d>F2J5Yg9ouMi z?Y~dIna_&Ox`)ItETzx5AXgjYY@&XBaOHDb_Y>C1+}H|Luw83rtWngo<8oFsCcxV$ z0sUE&qa-q=wjy|&TJNL{2v%sbQD-5nFt>uX{evJzXS6!-b{SPJ`N`nFXZ6>@OrG8G zGM5#x<$IAaWzj{uRJPA{Kst9%1S&*-fwS77bu3C)=~NBRMj_;wkDzsZ_Mf@A4wxNi z^0~v1C)OL>-S z7mhDnm;ncmEq@+p?!nrhwx>TCjWnZ9kkV`n#P#b_pw-yY!;G#9&8%OHo?mvtW4ML_ z?DRzOwjU>{bJVCt_1_ag(gn+_P2Xe5Mm?XWC(J-it(x zEN*Bgqd*mBof_tB#^QdM>kfeSFmwLn3I37A*e=x9b)kX&^~oy$`1UN%A)JO|f7#rf zoaM^>7P2ixm0%fB2`5+mBG6)iEBU@Tr4el9IaQ8Gmd5FO({x}D`oNAq!YbpUcQ?G1 zGgGj3yyS1lyxv7XrTO;J3DEjqvC+Ox$Gwc^MA37S2huhHh-ve>$uum16!s(UfdWarO(aXM262?upUM zF9EWSTJlc{q6Dgc_(q$cdNVZ$EZ#GVj|mwM1BbYeN#m%iBh^2VJUl(RZwEzM60}R? zxQw{+q+mGDAb5m)0<5uiB6bd+(kOdnhd$ z8`(~5{U=zP9-h(UJ|&g!hqyp@_Fh>;B+CwuZWocGa@n=PK)MlPA~g|xsvvWCwcXe< zEg5-tIf<=-A_x3pIk-_{#V-WBD0_xecu4aDinIZhtWy3wP{BL1F4-YAe^{ zLOqH8t>8`pVTSYWEJLtd`?Md&d801A1-8wMM-(sP>=@z5k?H|mx3(pFhi^{KJlp*G zUm}<1yz% z#;<@6GyEGOZ?r}F+}|bT+X*wIQP7VJLW~j7<-CF4_0H=FXkM1#KmsH5NVd0JWYx9$ zMyMe-w>QzSu+Mzuv|}huJ2L0h&-FnI(x7nBC$yKt8Mgyyaci8G1Ec1*$_H+QZkd>m z0Yl6y7H!>ETdOPd3tTU`#iPuXAQf~dS_!xtO{%mNmS|_oB&vk3X?wI@< zV4Q3C3GjiN1NL7wJTkVkJF-;!k9pn9hQL0G8Hks2tpDJoJlT_Tiv@L>dH+;&f+A|s zE%)!0jS+GWP=R{9-3X_<-pQRbL>zV=MNl=l1*#K>qvs_dl8LN|YlM(RK!`bxU zrrev2KS(L{9(3byP<`5)JKGN@S-ju{QkUAfm)@yhA9i!67!-0`^!icqkTK$+bP70l z(8%%A&tXSq17J2$98%R3a#J!>t9;^`Ygbq)r19|wPJq(<{?EEU{pS@rR_lbTDZ0;n zLlc5=xln@Oa*cKEs0P86(Ep1#>M+Ls_WN&fa8 z6I%c%cT(Yu7?pCP^0(iYuaeC}up0o%d}hw-dqTDtC1_W0%w7!8I|e-x5?xpMRJNSe zSrcw-b-(dfMQ>2Dw<~r>7Tg88Y8@I{4_2w!HSgF+wQ%2+UolacN^ddhD^i8A;FX?? z*p$)vLASd74_>DMR_+XI{A0p~+Rz~NVO@jV^FKY`Ok6&01~m7FuJuYi=w;uZE*)yL zK@75WY5G+?>=#l@TF~`Xs|DWfDD?-2-?~c=Yle=B9XJDdhx2~%^VICbuT;h1 zjZnn_XG^7Xy(0_lZTNX093pUwHD>;v&DyOl#o72*KEj!fh-FwJy8eIf6vyF8NKQqf zz=|xiWJGxf^I${eHlKe$|eG*bfW<^o8(L?yw^XQ|#eUmkZ|r;=et|WR z)(zq5#1{l*@MfXgbNK5#!gwC(f3dh6iM6lUEw`?vvfVz8ZZ-CZ~KI9OZvcH8Z( z=%$CUU$wAzW^4TQ942ChB;8s-{Q({N0Ld+bwi6iLA!aM2{T+{03RLy$?D~#6E0|pd z8^2M^v_*Nd1`?s0+IDGX)`8R))LCE)EuXMdzv5>hz4{R@qNNy1|RBC9)fIsb} zAa4_Y2;S|o?%;1dwYtAKvya-LE|ar3@D*(66x-nkfsZ8%zB#IFk(_*db#}=GmvI`wB6~c!KT2HJGsP)sPBWdIE6F z-?mjIi~tZQ9L)mT1~L)E49yZFj}27hJ0ki8R<-hI-N*hHE}qg{_R;ALOwQ#?gq(Pn z3-~E+toqGPP9$=PrE)145JNfBBRk_x*iinv6Z?_;M^MewW;uj8SX0J95LzO7EV$rjf?)|D_AV z7Jz$o->=3XNdPfd6l`F4t&C^Z8vm`l7pYI-O(9D8XVrTi{zV?_Lq-S7bMV$NQF*;l z?=!6VpD2MjNLcIx4R~wxrSo|z3+ElF!my|G(4dhs@*JUGT1_S=^4UxLs+sRM1GVp9 z{}`HYvYY&frD9mjD=d$b%eWFGx$VaBO)%upm%5wzSkmDrBP7Vz$xuqg7q1Yzy<$xw zoZRe+`yW>G_!m#rMqZ+7EJ9#2ha)V@lGgqh{Aq4t|I1~7wd(b$q1u!8TxK1{j5z-i z4E!_r{0I|EYIp0g3Q!u~zQsO3C;X{R%{$}Oyuwhm`H3A)b;KN1X?9EhYxX_|R^7YP z8v{=t=lCE@-z2ZpUw_9@yp>rcPPTf}LUCZ#GI~Y+$pZ2t-Wh3Q6+e$)U#BSmkKK*! z*izbA<~WylD6h6#D23=LWBUchY}HDp9H%kD$fMQqcEtc=-v+P#AC_^KjTq-$3?7Pr zg6O&smqb&pS{VG9)8mzw9mu*Lp=QKQTwc6XLwq!!QJ{CtY8_TJW+gyb_c&w8frR&! z`BuhOk8tJ{9@u*iibi!lnodmcP4W=nO$_WAEE#4vC?a-BLI%_NGYk_|x3=+&RG zpzO#wotCoC)qkWg)nopA_4XBdt@V9P#&G5B$NZ$|Sk|}v0|viSQY0oH4lD$@7k+6~ zigBa87z%8y%mTJ*gynnL1cPvxv{*$MJZtAuD*2_8eH6_fe>}9QJo`5O9bEq$P|-(o zLh$Va(Z2XpXROAGf=D!nc)<;%jDTLC$NAnkO{b}hF0ohOuSkD~#oX=lcubW%Q%4kM z#P9hbrdTZRHj<-G*y5F!RoFET#SFGUi}{qwCotWdB?E>mqJ(&=m(f z40H2`lri~M1rIWtNH8F;r#AWGnujUY?KZt_#qMm2*Z$+2NY*%VPmNUnK(tTFZ1LK~ zH5WBNzya4VX2eeB4=D&m=geaaJ(bxY>KmkcNo$H;^$34yT)F|G(@a^mn|H*5iR+XT zi_{Y80owI{_JI1pH@6bVZoZ*=qdIEJv{zriG88cx@ZAjXLSV*n0)qv_ZR(jMY34M! zAww>)Ew@xt*lUhyzuSD(NTnp4F~(8Qfgd->L}J@_K{ich9vS`t?Db%{D72d_Iz1=M zuDsjxOge@Sp89#hYun`QTcwo*Cm=PS9kQVm*t1zmo4<9i56A!KanHbht%>`q%PNmp z(?Nf=@y4 zdea|4U_{!l1murz3fnfhQF-njW4e#A?z^By7S%fr<|7wYuw2CGC5I5OBI zHfZB;Pk{wH?Wa(--YtsMDV#&jH=;9)kXX}*=$g4Qu6hJ)M4@(j+4lr}Ad%~O3{4_3 zy5NtNG*JE?RmPZz;hnM|{cl9J2w2rn5h7c!=gl4)J~KR16QeU+d&t%!x;jVM8#sSb z-c*gT&p_=M&t=85rAB971yjmNi?a=g#hT1JQ3F4RBcG|PE z!*uBY+yY14z{T%-4ndtx*5a{J?B03tw}M0S2`{@x7jH#-Lk@Fva@bBQ{dK(1je*lY zfZaQ8jml20JdOnAvgQW_bq|bG;I`0SD2*+HYpxzxOqaWARDE?L)Z?x39SKgkVP~-~ z;^M~T4XDh9K)U;YkRwT@%G8*<)%t={t0pQwQ_jyN)-sZ9r>PYUtsL!21#oSqeYG^- zNkg#7qT@$Qe4tg!d=J2kZz^Xbi)$zses)38fdRgtXhv2O_mReuwL>&I^e)N=R5iOG z)@wb9h(5LUgF(tyC@J$jlIw8uZ6wXEfTMF)ckG+ZD%teN@`6ics%QsC_-#@j!qMPb zb#v;L`S|GCGa87W6tWF{y8V{DrWw-A_GVQpcPCznXnecjxzQwZ5ggSPP3I2b*_1k9 zVHEmgOj`LavK#!(6`GDm!-4;L3$y;B^HI`cExwI;{{~zPh4!UULyTOj!aTL>qv*4@ zxHj-+`bt9%)mt%*%gI8Yr4B65N^%VNe?)^1_)Q79ZVO(Fj40IcQ$SzQT|C49oRD@n zbtViaT3&K?b_waHnB%$ywSEbl4f9bfLD-SuXdwQ!aLx$7X^}wM&npkSpw(huz%gQzTThWWadId7kX=KuR!MiLGZt|Oc`3Yppt-%o}$J|Bkml$94} zOvkFr;`Z0EYZ&Essr6p@LiMb@z0+Z|Wco8yFKHXp+qIw#uCmPiQL*E|7YZ-<@c{~U zva=}3{%za9N&&r=n6t^&da}PYV8@eexA^_aD_T;w^H_98D)OK3RH7khQEPWHU;iJ0 zx^zN+XDyM%cfD|!Pm0qM`_(%*hC$fM-wvAkJ?1JRjwqR#x3-98`U1CWV16ZwK__s0 zUE;aLKMy?y8-D1NAZfBK-G>*=HF@MDMd^qzC}1D8@9F~9nYv^VGbj*;c4}DUX8YGF zls86x3$NaTwf>an&ak@o728IXATxc4-Y#G0o;)~-FRW^Qkeel zEAKNk=-acVlvaHmRZN>3yo5xf384b?XnxHYr;kkE?xRnBa@ULTK4B@BCPQzZkk+Z1 zm5hMSm>qf!{}M31KcoeDkKDR*qM+%P*XYucVn@7!>0QAbzzk@gp-wMAa$* z@lI167f7eXqNSQQ0SB8MraF%|P(SblCCB&1ptoC++|kSCrN@c zFlEB-`C;!tKzP%hhU1?T35}=X@bbBLwJ0DrgvpfM%>)28Gs)>M5_9pKtKXW5u)&+L zKY1+(cA6{wk8%56W3?emT+17wucVQg4A5^H3kHE04-S|#F6zUFA~gaUd9t$PTAr`n zTvH9^FrQU7_uutHN z06X{1(OJ1qI~8Tx$cNf*!d@nGI62@#jVwu#jPNhRxKv(qSd_MSgW&3yOkhUM_ADW0&yo~DP+}yK zw-Q6W3i(@Bzo;1sQ@8Lj*FI_T`wOw`mnaq5iX7vl@TM}4V_777oxbpW|G5a58?@Hg zsVeIw;qxrP|7piE%DiO&o*R^SKr}CjM<|35Hvg6<lnerBkqt&K69_`ZCIRVO7wx7z8Z1B*zFJ^%|*LLl>( za)ujYOe!#~;}J@Vg2%@%ro<#DbZnu#uLXR>1QMRq2%}Pj4p0v}#$)-q2c`gpgy8kX%)PySs!;BulCKV~i1qnZjR-OqtsYC!uJZ)q}CAH3V#|X^npe zBNEIDpEn$&oVpMPDz=D*xN_!Yhe*>b!n!Gac&#{OWVxwIJ=ZfSk~eQB_4mFR!_dO? zH^d%Eb8s||Q;dA}II?sEP@_0kziNy7QB?^Uew)*BS%vOOAE^kV);L{4@{2!@sv9mp zoLG<<%M1g6m$=SEoR}gWbhpKxhxwWlm4=Kb0VM+N^Sz`0?kJV(%)@rDoEXz3lo-@4 zhSDH*k)6Z4{Wd{3Qma?;VnnKmj3n((&qU7Mc)K^8%pn)_u2T_MpygsJTU_}!|Hqo1 zn!~rZP9*Wm!P+hK$ZlkC=b9ah9_cm^@w>G831B|4dXDlM7Ac>+d9o?r+NWtoxvWqg zfb2YV{vLzq&!cgPKXXPRr85F*BTJG~v7%~J4*;?D%xLyFJumWO6)30)Mr7N4F2=u? z)zu(18h-iPND4Uj=8-NBRA;b_-+ESlrxV^nH51Do#)cF#qAwrGp+A#c@D}#n4fZ8) zN{}dxFyqdOJ?-7KETDksmGb?u=fZdFFsijCLHOq|%Cp`{E*H`JVX=ZKdhcDoqlLT= zsz%p23_NtzOCg3>D!ef|wWepIC;7WuCCOtCL>5D*up{zsva{m%V1JJE-=moz`x&(j zDQ67kFzOimzUgbivpq2r{C|NaY0>oDI?VpRJsU@?QEX|&cS(Z( zhP!5^Q+W3bUX50aha~|2{!$L0oQ)qWbMPFrZZ$5371MN(KC4PMupz6RQ6^v za%geok3Qz`=A0dX$~3l&I)wh;>3sZuS$1IP&xAvcm0hdI%+JT;HyRWO*-Nu)Uc2H> z-I?9X7zpMA&LaXi{_@c~VGlPseiBL;A{?Z&D4($+f@u8H*2PUAk91`|#O(HY zc6{Kp=n4yAZb6QvlK^xt9HenPmHeV61O$FDvu^Hw3z4P>+L~TsYy17E9%^CvUg*QW$%~7 z9Jp<|>AZWqWRGWb%!6>VU63L<%fwp%PM=cmLiT&%tvy*o<|>qWquj&V&HGkS#z<=i zW=$h@bp=!c4H+C{)w(ysE^c;50-b3K?c2c{@n$T>p-%J)X)YtX35M<2iAr!62VS_h z@a!R8{0)3AXRv`2Y1Z!b%%ID^Rxy>$D}aEj?7umWoXio!$sQnUdY?r!8n~VJSpqv31U6|6dCwE!5+|#1fmq( z7xo-pnCCl!%uFfYkK^?opXxMwxMc1MFKHYTj;y#51vf~#`kdF4Yc)46QezR5RaYmL z6u{B)7ZP}c9tlGbMD?jZKx0vR&==248t8N=h6tza87n}u2lK=Fy@Is`d%&G)SKd$U z$>ocz=TtsWlLE^6gWrNzLAZZsIgJ5@%!UFpRu^LJMcx7Bh)SSiAnPrA--%n*60i1H zm0#t;*bh{;X0Srrb$Go3HN6yB;sdZYPk@`Ib2NEP0+V}XaTAw5wT2BnhULzqN9cPV z=R^%9M&^pPau!e%bMX9EvMJjHvPK>_wFINgz%k|5>7A8F9~5*dIA zQxWfo)#Bz}o%|TbG;X=l;mctai*rwy5VEyJx8+wyj#0r3dj}pmBIb-DO^aFBlOe_f zAHDqz@6*?r;KTb}SRii_t&eaP&tVv#vW!L!JtaM!aah=KbsJ?4f2B0gXxTo30K_GO zB*~3~TWH{0jF_8Bk$b$vO%;))h~&UA;_7R|bRqY8;}xeY4w=G*IlJoB+!Xg6N8<$W zAr2MKxTC>5($F+mlY~_a*gkFa*C9gx9fvh{_r^Pajq-`%hB7i(81OaM++6Jqqs8M_ z>;}VR2h>eDwWzOncmXPD-51JX9hPCs_S zF1+VuYvHbU=AO+>23OR}ZH>8IFunWd@$tuPO08bS$I1>c-nC z4KMQ3wSg7y4rsEtD=nH|p+!FYR}OA?(iyP0vUbk=?r@5lSe|w-?|xVR_);1tEA4Yo zR{9Cz#_%hj?6%?ROV6vY?0Yg=1lSjIzCdbA;7C@CuzypyGl@ZVbRyr1Y?2JiVaaX6lXC zDUz;3a($r+_Xn+F7yXBwnv(sF{Jc?n*%N(olK7(F^)Qc=tsa+@Ezs6a6*(3 zqkkN*Kc2o28}5v;m>~xG{jTK{wRcL|e@StiMtG?mv4&@*5g8Nbu5DYSZlv9HXrA+C zF2xT2mp-iwaeKTszR!&lbQB8%Q{Lce1)J?-KB~QmZyfsF(MrlVvvdQ5<=fkTYM6kQ zPKG0L`>4lu?1!y&NPtM#x#9jTwhX1K-4jhmconV*W53bG^ldzhCGl@uk<-tgJ0-b3 zM!_jh?=pa#6Hh4jF{=x8Y?i>Xa`L2`QVp&^%3x>{VT;G~JX*L2mi z{zkGRR1OM@CTiPXY7rjcJJQ2lcEUDX>UJ8~dYG?Thh`ZwA0_4GvF;~OC1GH%N(Pyf zycGD7Gh8+KOZo~jF8QTJe>8wR*hob30P{A_p?WrZ3eX%;HQPxw22;i)u?|hBHI{E2 z_FP|?exY{K_P(K_g=382u#^jQ4`d!lLlPSU?=FQZ_RSn8$_1nugW!EO&s`pxuHW8$ z35dKaFmE;Ty;Sso@XgBq=FE2gJDVjkB8T}-Wy`sn@B5+?jjwKd{4v9q2gRBthDBl2 zy$aD)qJ}xHGkeV}8=x*`vB58>`|evD_&=7;#hvN*|Kkp!oI4<=>8z4dl3|;qQXfU7 z9Ks~kDml(+wmBqJ7#-!b(SgcgBsuNilqH8LGC6E>oEkPZW_Iv(UBBP|@P1$SeLr81 z*Yj~BEy%#usOF&)0_uWuTo8a&lNT#k3|98eP`Tc(aNkek8S8SMm96~&Ejm!(Y?y<1 zg@B8GtTPx!RuC%;LfG}1%zTAoYCCBSbbAOMnf%o@HbIFyj_pdB`MuDYV5t2YmVgaK zChS-WF1v8=%UO$+a&|Ic!i)Kbf<~v1T?W_fxaY;tYmpwdEG}vfqb#Cu8#O?jJKEL7 z+r--Yii`IDS35Z8n9o~N-5L=w`|;E&8-gT#BJ(pYs96P;8Tr9>XOj_X*^70&QSzP` zU94&I%WS}GJaxG(?j;kn;lXfkiZvg>cSb}IZLW-;)?2ysf%|MGt`+^0Cq_E#MKhd0 zk!qX#*M-mvfJ2o=6XFLLFEvT~iOh1VsvXo;WDK-_f$ile#$xY|nFM(y%V3@!6DS`G zIi!>Hr+(%Vc4OMwh<~gKYqyz%rX;8{7f%^|C!;CN{>7%7iTUR<7xcQc3YNyP!(Haw zB^YL02c{;B_b=~&uTus>EMzsnvkZ4 zffTfHeFNszSSy3EH%OG7bz%DhAR1`f*_Zh1$5A0eVJiUkqbRkJEYa=w5;^m=eqDI} z87uyen%EdT5e4;N;x{dtyiT({9%hs;?TX9P^1^5!YfkWveBYlKRaIc}q?+%Y!je?4 zj-xs>a|XjBtSyt*+YDSx);dX5Hnptc|b7uz&<4#jo5D5*KTi?3ndOw~BO@}XCbm&L6kvuLS zIll|ux8~e<^l@mC!<3cDGWj0FCspEZ*Ap3G zZS5`#(d}(-N3iIjxrDI>h*qtRP}-1+rMecr^D{0?zvQ0YgHdD?HP= zocFxIm}PYee~8%I15YQqhWTfq=2qef6xE5d_2vbtcIejBi5D ze@;IH4{1haCU8U|8PP4alv(unX?Y!ph5uRV!wr`4Ma_&X6S|QgOLS&bC0$sj7s+%S zNkZPY8CB^WZ-)Ee?Y~Fyu<=h<4)y50MZ0jeFy6I9KFZy12YS%*gUScN_^22o`FiHL z@cIMoYCQP+W@Dq?H5ocqv=dX&lfaYu?U>aw;&>LN1j1UyW&-N)B=+FA{3VC?Pqsf2 zrXlrCBLjI7g6D$p)T!+|mUa%MA<+O9M3~!HY&b^@8S$(XO}#GNldwA8^uD0BC5FE` zrgLWvNgrR^_%Srfoer2G9H_kPgB?SQ;3}o!UOx0{va5SDb*_OrC_2Nm-WN0;rvN`< zzI0M=a47DS*4pk>!*ce-?$iTY9S);bF4>zE?bc!@oT%8E|5OCGH(J_*f8G{v{*lu7 zFY-gm`291OB)qUukzr|eLXs%@l3K(27?R6yQc~1sO){o_zTg7xt}7nfv%~pMw#lxA zpHW=1{_k-weY94y$Z;idSzVM3m16*h^L2J(VKvP(uFVPcMFKq**j^JG?|E7b{UCYc zt4teM8ZJ$vnZln4<8u*jCc6Yg_|`yZ;x{`2#YL>j%sY|b_iq&io{y^+HO}`-K=I!q zj5sZb%-oM~gXcALPO`!7qCXe}t&vf*u>~G3Zc-iV3XIxU%3IqWiAP0yC%#9CUEe6N zR-Z2qap9)<7T-1Hp#-Dmpn*G6h76~lJi|(Fe4qx|ow*l;%JG1kRlIk|!bcr8kAc*( ze~(UO3;*3M7wF9}fv%Qj<^a zw4w4$z8uC;e;4KdLpe}(r}5lb_nL6Ig20@ zg3|GYa2q_kF|^{Z>87~7x)^exl}luk{|ytBuzy8v2Ee`Ef)3tf)P>)?C{u`qFt=E6 zcxAchB65EWAQs~>{$7K;{7qcnRVK6c(R{+Z`v;hDkSWoioi#WzL}9{qka`ihQow!y z0zU$~+z|gVs3|3GeIZ}d)~Rs)XAw-4)rdUzV0&tkOx(H;%;@!pA5=qY~ zersYh?v8h3uMY@Bi%teb>i3mOvgw%{YLyV4=2)8?{Uh4zT#EXL^=hREFnJUP1={gUzkHncm+XJeS(-Am1V}Hwi@(fM=W0%(lx38My>aZrgL$BiL$q6uJ;_m zAO87KLomn^{hocVVL21k@Qp+}%7gggt7RH@D%dHMj($=MhBSvBVEYT$3K_@m*o2|x z*^lkzb+UYcS5WRrb3CjrsdzwcV z%M_CzcK>Tfh2Q{-jdIJ!5gpmxaebJel-hmR&v2R;>dk@R9Bh{53r(Z|A8?$mN{w2F zmdHDM{Gx4WSs+6~5&Hi`j!W*5V7VSfvw6_b{u!@fR(uk)tq0vC=cW!GRDIPBf3_{b zVZa`)`peitVWXex6R9phkB8(zwDniMZsVl9H6XQa$JSPXW3p~M^wlXzcD_SM%pVmg znkIiJnQc^b6@$2>dr9lfNMAc+C6bmyf~0U&yc$T)50@_Wc$srMl7bAVmy%k1U%Neq zq7tcAP)}yC>S8?iLR$?lA+krAB8;ol2-0Y{_O3S~UU`&P?Tk8KI$v%82^FjJQ}64lQZ`sM-G+@QDbu^w*Df z5uLduE*clzI1;lth6Vbtd0`)Cyq@Zu;GdkDOARC2qZ^mkI|=_#>tC2YQc>N+6}1# z*r<0NhRF)~S)D?X@nuQ2QnmnNLYB|J#zsyO`3zEwC`_C|VdFT|+LjFWZXHGwGQeET5qrzm7 zqk+dNJy0^f9OF?(6@;;x5?lp(OKN?%-Si>~3TjMe{KYyvc0fLM1unLP%y3SxfgW0^ zc85oXJPhA5Jl|3qmNg+q1~3b5H@rq%Fc-`n{0`Q&aq}{F5TT7``)(>>-5cGQ8;aYA z!^cd|^{-zejZM`l@idzQPN+?;R?9()d)Y+#S?VprbtbV7jpcW(oAlu>+(@w!X7khp z;nv*=kC#3flrjy{ifnK!bKQlT@n>qVJiy?V{bJqMIjyQsYU>Q#su%Qo!0&{AAmJg+ zHrgLJ4{h}Sg|1%H>aO193Hkn(se16|jrjH@V^C%3=*DttacDQ|ouz9HtJIXCRL*XZ z6hX~?0!YmCGH|0YBg>Rf8omkBMAsf>)R9M8kV$*)CaGm`vA6d8Z2&DpTU z6uWn)-13(qB^`!14(rsV3daW27J)=UjEf)at2@3CjO{2^lpQ@?Zu3ucqO(bbowwoFXz?@|9a>da1LmIbyMhaOXQ&Zs(@o zsCz#n)1>ar$w_g9%B`D%z+&z4s3N694fQy7ywsC>BYw2z%;Z+m`>uikOoM56s@&@K ziSydmZ>Nd=*fcoHpw7D#6#uC3(PmjAi0bBHEs-W}jtQ?mw}X z<=ve$Nl_;JP33gnOMQctYUYShBB0AZ@bAS8D8n=9HuDhvqoY;QQb~T^gVUsztf2qI zO#x@*m(OmLH($GPmpUf=Qy|ja(9_`TdYVZ;V`M7B^)bD@> z9~+%?`v~?e4@|SvWg(kMq^YpN8>vA{=b3hf<+`+t{nxzOtn*-Nq$^2JA+*n-ucu2b zN<^!F7VTKpw=DLNbhMbGeky~t3hFmnVQLDsi$?zz4*rSKOqHFL#z>?igt*l0e(4D% z=eFz&?7V!>Eru_WjX8X&?8wyZ`nIs$RM)-8G#Lq?XZ1ogv_UjraE z;_E1L&)6Tyq_ZbnG=$X(z`EaDN#RjzS;})kLs#>+&C_-~q)<5c_NT;)?7dDeMK`Mv zb_*JMSw=zVX=qtW)6uZp{}$HTtb!fd){^6Q(%6-=>0e@S6kznol%?fDx=>P(7I9DAQ>MQAIeFu?h1W7TG{LrvT8~@Z?;(fV66>UQmn&)pMT^zA4O09 zQtFUUnjEz1j776a`IDiD3-N^`DvJj`7LP|6(^{^vC@G>MxggutPPp1<+vuzOg_hhf zO~#!uJc}PD$SBvx2PlZN3z~E$Lxf|NkA648X2splM282iFy>4uS6^u+Uw5!2{pCbi zz^0lA{{4!TM`zAR;=={SeG}ofv7dHOnj{DUjg0jN zJA4F;Cvp4d8xXyNLTPh)td5GwQoYLLW;Wg6QE;;tzcNO3-*YP<)VKJrQteUv-8hC+ zd>)szjd&{KQ15n)@f%ni@_dTdSsu3Sk61d^tRICM6y^5^{Y1a?3$jhT+7!xcoRJyG zm&@C|!!7-u112rjFW8^Dc2VQKBDr4=JNf1kc?Ts-Tz+=;-i`rbi_flX0aES2gJhk7 zHm$vjoO$H&?`nLj07<#tjGsks6xoF6jufxNyHZ@xy}UJj)3vwR{_m`{d|}{@MR+&N zNTbCHJdyA(?xR|sQ<1)mwI?tL&iKCgKn`!uy@bxu_b!q+6XpoC9M;)|pvmz1A22mw zM;jrg`}C-bZrnCh)=l0q7KeYQtA99O;FO}#88GLw0VJ}PObJ2${zuu5xAtY8XAZ>2 z9Gcx7Uyv>rOhqMp3QXVzdx_{mSZ{Cy=AmFIIu-$@G%C(Fj}uY;&<;w{a9=)=v!4{s zVARO^%SimBg^xM{l3bbR%;0IH-CUi$wVSCGc4B&>zxD^>nTbr68@$_(y0?P-dor1J ztI&B;P}RhJxo8gr#QLo(GxzMb!}(Loxe$XH6AQsH{NI}2*8iS-$xUc~bV&MY_P;}9 z#!Tm?sL%WCssxv9gqNLl~Ba0I#h|l3a!IJ zotmeaIuU#NK~8r25x=fhR;LJjB85_jF~m$NYL_LhqGuNB7lei zCv$QL7p;C39D4p1F`7ATP)UZnhaL_)jiOfKet!>5UwUu&HY`3rLH}_V-E-Wa9)LYE z)sz&U*9>k8`;gABbF3NX5PT2c*mWJ#xt1BEU>nNP!#EvgEyv%Z$?=DS(lIc;)MLEZ zDjr6YPS^ZI2O8Q$fiuyC<85{~6>_F`l`8buZ-#(0dy7CUU;R2Uy$W2h9Bv%3=pWM z)v5-WxKHw4PuKq2woWw?1!0`o*E+P_;yNTvuU0*_VV9wXOL=)4tr%VcTQ^!6cwHWo zQt8j?x)PRNly)&6QiX!iNeQbouW#=DN)8x5SGrg|&9Q+MKb) zor1jTwHFjaJjV{UT@(Vw3r6=|L~>((#9E2aU(Vs#R;iKvD(Rzf9_K0_i>mx{py$vk zjx%vmAr^cGq8L$_sQqg2oC~1}JLsJ?SX*eqdu>aaqgVl5Lt?o@bdlmDX5D>zMrSHSASQK! zkSu3#<5?JtWtgXTkxCutLa)CP+6^}_C6_G?w>Xr6D9QCVV>58h!Fe}u)R0BjI)h%E zK$}{rKtUSR(YMQv4kfQY8tMlr(f-CdWg(d%CG-+C@SzT)Wyr*L;oq1BA^GK$PZs-q zvlC!-S&8=#RfuV=F!G(2+Sk}`EYqy4%1SaAO{wb^U! zVvwKt59BYOH7~cS0(A$_tdIJv?xxr~KWM!J?^ps8Zl3|E3I1>p&6dTTUkWM+%m$kK zS*dq8CfwU$9In13w#QQFsdqJv4rrRcW{`S+cK>~lvZO%S^^8>x*W&GLf*&YIj?={P zeed)c0%p4I{ih)5yJ!yOJ>k{Q*?MXw@R6>vo>Kv4g9w}T4^3|k9tP}GEE15d*Dvn) z80tYtXfF!tZx5e4;@o1{q+Th{SCtVxfE$e??XVN50`wd-Y#ISJ>Izn=mh{Igh?tN> zLp;mjVvx+&0OTkG(GNNn_ExT1bwk{-5dJ6h;7?FT6O~=7YTQa4|JE3UrH`LOGxYB~ z(y(xuw7xJ1YeSUmx0_BIHqmVI^{jK;J5}QOvl>f@I>_~u!jCHxob*1mi z+G9a?{7s&+-4n>VjLrDH$&x_Yzi2Gf$xR`SA#0d(ier+6u$~*Xv(2s2b;(818xahBnWQoKhMW|RjVRuz22 zj?nJ%#D9FW3@#7r^N?PGBKvmyvQUN{fCzbkbL8oDTRH+qJoZ+yYo!qUZYh9Vc9QMG z(IAT=c4n~p;up{WtH(GYl1J~9g7ii?4S6hr2cFq?!c`Wi61HSo;<1`KIt>hl?q>x3 z+G>=PB?B|MH&Q`L6NI`%s?MYBJ^y{Q|Ktoi*u_fQDZ@Ey zi_f1Kosx}TL}Tn?W7{NeKn2@E#==bp!JeP3ucg(-c5yY)DNw<5{3asdOU$!!A1#DZ%zP3YD;L&&I`=AcMIe@CyJ5B8xpkrFB z!yNCpod{MUedLPxAyK2CZJdIpD@AZc#`0k|`?hm(U}53{^3~ffRC#aiKfOU08ahEy ze$nk`?4qcdSo7pqV9_h(J1qea_jlG!VK(&|YXpi4s=yLQ{TqbzO$MKgaWmU+0bENg zm801-XA0<7T>Yt{qmHD?$FKNVmUcqb>v5Kr4Zr?0j zJT9npTP5<=hJ)h6@&ck7xz`Rm8+&z&;POnX9JK5hnctx+<*fHv;FTMXmHX69_OKd! z5|Oh(LS?g&uru-v4sdHL>vGoK{o>HpQte|$b<=z~TC%0)%UEI^?$CKsBexh>XXxq_mk2XuvUsN=!m5?)e`?o#_Ab(hF0I0iJ41HDOE}1vXY6Uzh&=&X56j$4Ieu^LWznswO54cQ?zrGi zWQVX~f8HgUWhpbG^H1mBp+=okS=ynMIrCQR_;_N%-^MbL_(bz_Ku6;>(EUg^pu#2BQuG#&1@Lo|Lm_3fpQ@@omBRBoyZf^$lr(Gq} z;D{h{k-FnZe`IAXDdf z2z;kit*fAZY$7J+z2lXKrehO&rVXO28eh+vgHqm8#H9uB$y$D6FPG~VucI}(_^)fu zw_PDr5Zd_gsTaulr?!v%t!}sE8}v?vgElDZoRD7! zQ&5W&h-OYkk9B?Mxo9^#8yLgKuGnxIN(|G{fay(Me`;oa=QybI*1=!h4P_21mLV85 zs8cClr681PwU0gQ0n}LCW*XyXlJJVtpiV_Jhnr9AUUp|MsSoKt6)fxwNITc27I*EUK71|F zx%+SU^QlYwW;Rsjr8lDuCoof^y-5y~Qn$DPnG%%ESDkL}mN5fny-WvRH*|u<31T{^ zQWpV(#)N|xV&1e&YGSwd#ii6-n?l4~OP2_t&BBH83+#Bg&>JWf|J0?tH;9zF*ehwr zIVts@<0)^=VHrNNc`QruXzfPF+@<8VC$sihwM~e^#zawGD&GCiuz!M}jwt}$JGXc6 zn`BH~QiGWK-sY{AJ$DEzaWq>` zww;X5zoBPwmm(^f#b=73&R9|789|l0?1F^5z%R#)>Wkvo5LNH_Clb4#x1ZWsoNs>Z zFtJ_PHYTw@H3phenY{8sViVo{+bJaBsm8B1-gmx}IK%z`U~nP2(mRE+fo|O`_hXNX zI06KXp#E%93P^XS!+A}J(Ay41M}yl^<976F%wjINT9Ey>xXL2)ENd<@elduxN`Dbw z1+_p5%od^ydm53itag3YcwyR*#VQZFtWK57z_%!Y%AQWu&_$5hL`iI|f_V+!zK8hi|i-z&}M*bG#GI4lD#|B-{Q{w|kKzTOXg za@Q^3kwP?Ubj~IIM4)n9CJ(98{j`uy3?OC3P2k$hQ`g6}(*g{)2Luy$`1c3ie-|Ad ze`jbfmDiCi$VG0gKM<4cHg9>bzzuPKQLng|yeRTEw43i<48MP9N@E_n1_|8Ru1L&c zv1*uP{e^8T!`9qI;51svzZ4)v?V@QVcEUNx8Le+dHJ+9k}W(PZBIp> z84;CNQxS6o4({(x&%8!s?FrN{z4?{X4;&M)|boOv#T zGcfT{9$fLz;Ti1$yJp`jCjoV{JY!#%6%PP?{M8TVZ#jyt(w^$s{`1}sR*fh=fm(Zi z@eztZv!fa<+(_R_3MIH%b6U1#eXln{d}7QR7=5q%87ea&yUa290(+k|$9Or{g$TBE zC`)$IXNCp|@<6?QLxQJZQ0Y{;!G_`|`bZC5B))ZS;VuH2*w(xFF2GgxA3xkw z0N$%*9C2TE#d1J{TgcSdP8Ip({16_|s(ChSA9McbDjE_vJ=&v3j&6d1U!5RS+tqI} z_GT6<#69T~L0LmaQh^?+haZBi`+D6hOkIw?JJs3-LEWvCR#LT}=Qsnx!+ z$|EW*RZ{~qM30WgZd0f34&g#La%0*pjb8!97?v@XheC5MykI(*({se{X9N)0)q+cN8H@-#)u@Bi*=<$b4^ zrQ`w?Ijgr6$zkgf&Cq7c^^N1vY!LNT<=Df-bOjjhww?(}Kk2O=Gx*_cgyHjW(sZNF z7Va%3L6_17meX6+4pVoB0(&)9ZQw}awI6-RdYX+{%iZEs6>-*(kv}!OO7X{CBU`{c zx>K2Rv#e{BZBj~}gnz9j+^2Uz+bWRLZAhitow0-a-XW%}=sbE5my?Xz#x;GEwKOuw znkWK1Kr`b{0?PE(c%e&w6~~%9g}$tbigva;u>e@IDV@FzZq!OtA z;_Q2=_f0DB_GtEAN<^*~oymi!3Bi2a$@)1VT!bCxGEP*=;R4KV?NUdKZCyDO;ct?i9hC!D&QTb-@NFa2o&?K9f{DWS9jAiT0&&(A#*2r{{eT!8#O_-uE&SD z?x`Mx9UUY#1{g+1+7-anMX75s){r1u>YSocX!)dpplQH-grnkQ_Oy9WOhi|nUh?C# z+23}Lgz05<+uo?-CZQe9HutZf@Zi#}fg_bVnm;KKy{Fm?rs`MXDF_MihYxq>l+_Jh z%?hWV2f53ACmCN*e|97#U}qwIeXvGJTK_~R^V{4<>9KPLKCj-7>++mkdema)nL<_^ z&IF8Pdfn`Grovt)gX1`y+dv{BvuPR8NuIK`COy7bW`5_o;>>I+c^cvVys{X+)gV;u z`uR3-9=?8qdE{-ZKG^7l%*wqP9y?ABsZ{NeAq<3A%sa&X1%+KW`F9 zp6_ftTK>LfP_3aeoRK#vPpm6(-m#cftu6B@8i+@&b9bwxWJ;f6s5n3kjPn+pdmz1j zia}dsXorkNX{=m_I$%u}`I+}pH_tFh2kEd6-1A+c_Ly1EUj?g|NbsAf^$Vdh)`LE4 zTa;pJtZrXAs?-^yCg2v}CVA=cxD|c~keV+D*`fpU5;eyp+t-|Mn2nw}49eJ~1P=*G zTi|e2r&tY*9h|r3hr^T$JK2`V-f6c&#M?%#W7VLd>~$s9 z-hxR3uEAo|j~fqrORwSFzd`-w)(^Lwg8mL*LmyoH{(4neM ztkfr5yInIcF>F%i`h$D5xIK=d2{F-Q!hi9edSz>=1+7WBcU=T1do6Lq1b)U%jUM2b zZxW>71>*c26ob9V0s>y4;MR|;8`fi7{oDMBQ7+cb;7g-?qtk<1^CCuzq3*{DP@3v^ z9NgC=-&??%u?}Jy)3L%(RJ%r48|(GO_kSO==VOnx?_xW~`3)9PH>1L4a8a>w%|d_L z@aqlXRHvw5GrM?R09Y<0tZ(9k)BrcszROL=uYai9>HoG&NqD(PTc`Xs&Og;^Z@@g1 zh71q!qRbgB{q3c`e$g!^rQ=1=o?uQz!^6PmnkrB0*l@H6`aQL-eEcAWMJ0O{(LgA8 zkA||ioWm%lh;BU!PSSfx=!01HZyyZ8be|QT4|TyP6X1jTYV%+`oW|~y=_mr_x{a>C zfC~#ff0?J+AGWh%+fhkpB&2^-_UMDRGK0$12Q0c2C8=oe2O~y(Vw*}#$ccU^E|+%O zA9)4=!}fDTPbLgT8ZkN4Ln*+Dcri_DyQ?>;`$=Z+bDD};bz z{*g?%x`g@psNldple1KC(;$XNcW7RYv$GeW_RemtsAGVo$i-HlLkFx+@s5HVzyrJrFxut1sTh=7^D=$O8f#s1$?ENQ+ zTPVu+2rk!qw*t8j`|Yq$3wK-4_P&ZukeC#8E53)@#B*yRA}=ULb@5Vr?G3ariv7@nb7$YgwH6z3Dt2L5sl9q zey)vfAGI_l-%au0$Qiq=o%TV8t=n&uce9lP96oMRAuLp=L)yZ6)xSN#G-gip6FjsC zOEF&G;;GiYobn(obsuwC-FXPK9cRooKb&lQjH#-R3*dzQ5tpr`Uht4U#qgVM>39zqiIhMuU2-a z9cej!=s>sSypz=vjHzvWf5c4DZBW@?B18m3EuGismJlYycC3OFaRoR>1^K~#BOXBc z6qIF#HSnMnmJ5||B5L8y$)-u6+1=qTrqZTW^U=monk`jh>dP!MwU%gZRcZ4w$bH_vcXqFm!Km+Z_6Z9w=_@ z0tE}oN?!sILLx`4-&2{kM4qe*Fe<_WvCzV{BFhuZm4h}39s5k0H#X3g_XyoOZR9uV zdfTWHLrLxS8=CfEpVB#9Ou|M2_XDLm0ASqtBq@%Y->RH*W-vT}y z`txnq>Ry&FEw!HUG&r^_&=>;m52IJcpt}rLR~@wPZ1N}5Nb3Upkk$I_v{2C0n)wX_ z=K0CtV^hDf1TBr~k-G-lh%&=kywHRnK@bO{T3k8-7xRaz^WJR&a-l(QP;fpuO?3d> zi(XT8TX~cd2=y#_!jj#25mP#c<|*_d-mP$@Uj&Nq)en>(VmO_3Ft?#QVw#{dG?~6K z!Er?GalPpn`d1?+CTDclhPioFTDKsZ7?&D)HJt?8_BmFvw`-}b2^;h+uVK!oyy-;S z)*uIqyw`?ENy;8%=svqV$6slEI)_}FrGF}1o~ha0Q+k76tJtuE78dz>`< zJYoAnYG5}#{|{s2W-ThcH!d=?_wQQeZCu{ks|MO<2aV-)jcY7KV6VXkoP4wkZ-<(} zySkyU^vb>w+eS3KY?x-?lYd*_?PTR`91EU$eRTz5dth41^6xQLi&;{Ic(ho`nx-ZX z2aABfdmWF~1;g#N5B4x7!PTkYw}S$Kc+w?rvNCHzbgl^VjCA2Y`+hV>-0M=6&Hf`8 zFllSJtG=yy;b?s=3v9SX=*?Ut7GZYV%%&C-?b9G>e}FOdZ&C%An*{%xp!^tAY9zKPg>Sla)X4e1)vR{VMbj!x{V z3BEE1PQ9i#BO6@Oiu6)jSwFtQVc1m48i;=IVQHcsk}J45^lbDU&vJ4<=oK`+c#nO$2R#B|JFeDlZGN*pmW$~ zAzWcJcwBal*FPT*o1@2=*rn!XnM*6tgElp9$6!%6Vg}h;sT+FiPi#f%O7_$$0y4XC z06NGZ!Lr*Aj1C0GZ($^(M*cwDU#jm|O*&!90@q%wn6y2ApfqCiXnFE@REDU-e2E=^ zyDy{jn2!eG4?V)6?cx^4#1NlrC6n3z3|Ue2M2|(_WXyq2x5i;imKr2?#*h|MEg!nN zufz9^_415#F3|av3F5*$L7CMMr(yGTJ3UC4HCLA+eDoaIb2wT>Ua`r_bEekmG)Ct5 z&gQLRK%5z)%6{v=HzyJb=z?8lcOa&1wL$v*OcMa*-IKRqKgK@w7QPh2175G z-#1;ilJ*{ge6y!h-xeq652dwuf9f5QchQhn9ba|I* z%$mCxQAG!NyvW%(a>jG(RsAV|R+GM^zxg=i!EMLp<0uF?alK*2x%@a!K%`oJv8Pv? zPjOaW9iP=oc6d!aG6w_agcmeq=J2k$)fSNw4J}y5?habNlZ)Ou@O$%8xvx(kI zOhBdn%P-!n9f`pz9=0PRQnTEA&Y_>0jS^p3?U#ACw#;T8uvPE%c|3j-F!?NoX6eBR z`Vuz38}i%t@+MwO1XccK$C#MF;{%rM-Q7<(8fCL>GIg;o zEkGk`O2wUTlH#%XGEJG`HyI;!d-qp0A z;r&(n>s^|4a18ezP!HEn7AzTRh&>`0wSTTtuP!$#Xz2(xnz2hm2H=kL#-9S-P-q&F z%{e=u*?XvBC>aH>)M|2!ul}ZYBzsbKsANzBlAgo<9c#4ZMmDwCcHNX35J{c}U7l51 zJMtok8a+F--6k}svS&H^Wc@QZ)xbYEZynhaWPCe7Dx`Hqk_*#wL)>&#N6A4% zMM8W@Cw0h>Z_CvV)?~}h1jSQs`aR#2&=1#1h^8g`;?CVz_#_C75IfXurEU?Az3Q$a zJ-#5ai?$_}N^D=UVb`LwFZ-%qf3X(gd!G5t}+@Y1VzkuA2qBQLJYp zC<~()Rak%^ylAiwem2OZK?6#g9{TCKH2gyp;g{!UVX_&bX5q178oWlg$lvi@<>E%q z!{U%8ZIMG80y7sB z2<2Hs`QE6gfQsqR27P^TXWw<`3d)0B0DawnDJX?wPA;}nyI4=bU*j@aqNkVFdNHNl zFz9Ezdc?OBBHB{DLQwXV4+Pbjs~o#2Y<;^!uoObMcJH>Iw1b|S+gLQGq( zS-WApg?4P5(D9z%^`~R#RLtZb9M59B#`Tibn`0J}Z ztJ?xQ*j&Rcun-ii(=;6zoKMOb+gERo5bZSwLub^*``@jo5<#Ey2f^J^Cd`F`r56>49gT+q-{*xlZ$pvsk>wMtTfcNuU&OVzju`?e1Fv ztEttXHQ)N?RnyeiQ%Oq89Q%2^#`<@Y#v9sfZv2&zS~{yF*BApYhqDu{a>`4^hN8S@ zq1Et0u}#AnTg1v}O+R&`WvmTB-o$n2IAIU+WczzuuPc&9uLJE_5(qvanOr})@%sG3@>dYIU3uZTnkdnS?PpLskOq2By~9a^T--%A1wtg4sn7?(LJ@?S5$c!s-dSiy?NYN)Yin zQFK>c@Iv&e_fIZo>cMK3fh9G^r0VktjQq7ej4m{7LlTbT*W(UH22`zR(h?`Lo5PoC zT_2N=@lxJ26!YqIR)1C5$khCb-GBrZ1VGqxqtHn|HP)VI&UPAYJcl7_3HuP2zMo_1 zr830=k}gj?ePnlHJ*(0bKK4%VhJg37NLTtdl1Sa$J!|&wCx8+4yLP%Lpe3-(blez}`;ie_?B^~pW{2dm*QlQ=uCFL}>DWsFpgKW3KFjX2{X zb(j|Lp-4K#G}RnJ79bxk`I6TOp##l_FoKVP;%B_3KZ5Juh23*-;vATl;Yi5_Q4Vrf z6%DK_+zJ?_v@ssZluh1KIUcW(b4*sPb|~C!$DJ3={d&iKG>5hpeBPawA~=doL-*KU z4`fSOGw+3k-lkNT-ff%5@pCtDq*IK*ILs?s&V=K(CI2O`cNj-QxPy22D^ajSYDJhg z?5Z1peR{D9A^%Yk)vNFi-mv~8_+dY@lELQC_iEKt6q|2&sAE-q>S5Hr6D2`@o%B7j+8eypfU_62uno$8wpnh@esiS>M18rOA8KSfK3f zn}A`Ex9{3j?hL`cKvk^n%OliQ&`+wa_Z2@}XybA2F&D*^PU+6ZDA+dru#mjKlaK9D z@n-HyGu4yIxQP^Gh|~yc;<;KP!{Hy-zSc)RAGi0+^4Enr-}hOGSW_HB;>|Hf>;70Z zUBq69?tQ@W=_-h(-UU%JW9yxl_TdBj4Pt5U)>K)ln3>leN61IGTZIz*1!yECW_^oB z!0Ls%$y1MQuy<973q{z}pvwjN&v@QZAp>!)O-!RhamOF|$Krt zX=6=^z5N^Brh&KS*DjE$@E7;*bCK@@>5Z$Qhy(}BVgs2>8G8Uy4By7NYu=qQ*<{PK z*~Z(#TkEPmx;VO6KSAt%0_ow^aj4l{RPC7ZUxFNXW~F3HVK7#9&vNrx zYY=#ILLh&uYaZ9-6 zM27=YB^TX~Q_oTU+DRvcej;qICQqAx@ewlhcaZW90e97mwSC@hMPg?WhCLcz3l)6i zJ>4QW;YPnpqKoOOr>VT2xLG6IM8e%?|^JVJMF&4H*<@rMVH| zIw#P1_kFFr+^)8SOX>dT!tZl3?&#?XN@sa4EF9$?%LnjQ)GCKYN_4}SyX7(&b1hPSk9$EovUMaq;BIHz2_75=Vd zZBH1O$VzNPK^#v4DJk>v8OfdVa4y*{QzM9EUr z!VEHVRBiWhi{%QyKVRLfZ->~NmM{SeG&%5Jf$*A(8ytv~kF&}6>jE5RHO)xIcDTqY zc8aGl*sTFZq_YGLxI%Ajj|e@7+$wz=z~dzxVS-KhN{uZHUz$-tP_+}|iFMJPEE3O; zT)J1t^;M`$5BHGOnB1AQ$Nc0@72xxyF_SFs$Dzx|IK4`WSb+G|I9!eN-JcSzU|`g@ zs7O$r5k&os)Q%Gt$6emXDev8J7Ds+9|uXm`I1u)!?O3)FxDXXi}uxZi%gtE?SB<5^GC z)i>Z?*{%WGa85i0`8bQUEX#tvn%eYHPxj8Y41Ir1rILGo7cAqp3C>MJ0Lk5);Vi^X zMm{;HP_$XvuETaxi?PT+7AcubDes5o8A)*rW45GbBZ(JA)pryX`wv#RRhV5&BDZ-p zbCSLS({t(}5z-#H%*f9UeZhpomti0OWw{``;7^LO*2HFHd1l5|abF-wIoSM;2|V@| zpe#9*ip)lo|4BTph$Njtti&G>U3)xxLS+JjkD%!M3t9)HD}q|UIjqo;xdvu+6Z}tr zTAX1EU+v!BhW{(*FOiuHL`iVB0e5Y6gZ$;VgOLo2W%iYcTCfJrGAW$DT6b^IQ zYT|PFF6Y_GL{k2uLTp;`p(7KLV|);Jz9eR(Y#zhRv|!%5*bofAMW! z0NP*-6^QS|j(C_Y?6L#K$|N)9QU|yHR@to2O>&Qr!2EpYI7Yl~=;D{XrETIqQwg{X z)GT1V-dt^>rISzQARMC@%omg5qrbW$v8B=6!4-ybH|7+ZNEw|(53#X-bbnDVk?*TM zbm|SWd3YJ6=Fr9!I4;9}M;HY3W36yv_3y(TEvV#%bK9y-drn^^@yNA4@mkGDc}f@B z@{fL8W=mv~1~nq^$X_gY`H#fG!#Ra`%YJE)hW&ap#h_9GT`+H=P$TB1Wcv)K;Xull zRe;?DciIL|?v78F%lbiJ8Eo7vBI>2}*q9~OPul)swkH~&>xCVNqSt2yAJK@ic!m*v z-E67dBFYISk33!E!K@Y;s#mOZS3VnjG~jnXj#v(4Vjj7ll(hP^4?T)8*vjWoLA=POF2t z2^n83AuxBQ8(?rS-6LbszB(Q7IeU*Go-}O z#Hzz=YID?X>x9LeWGcpfR7;9|95!d2vZ5)L2uR(GhLYp7X9cvS_nXQcdP3vA97d$o zdRf?8sI699PpfnO*9Tdm13UQCm@0&zy5ruBj9|7Z0GeVm!BDMNdD;g%G^0FK-w&`- zW6WPwzt%_NcS-o~fkS-~rUh}8n0fBI@A3XE=p2^K8Z6|! z2YC4k)0}oI^)OZDXTpge=Py9Qe7V;@0GMlKcmJ5mik~sxb~{dHN2p$2m1m9Pn2D=0 zQviIr96a!8flI6zkP2V8#|YD}ajQqtX&$>QpK>Sahhs=r7Yr1{JvXn>FfDQEg3gOu z1JNu$wb-E)Ro4?zS)!yiXR*)m99{D^sc=VrX}G1M@t=*G&EXuf2lB{HbqCy^Cq5nq zq3A{v^QNJ_h1)dLzMgbGF3xS}hhv>9E7*F!ekCbwbj=2Nx!I9l#{xx$?fgBsWM@yq z{vBsTWDfI92F?(?s=t0XjuV5%*mtPPaFy?_>;u>eudLaNbb!K*9!>gVHvPosv`0|3ytA|{{_ZC+TSj(LJjRVNVDoK91yg@F>tpK8 zJ;Ez_w9p35WUY2)6{^W(vRl1u=0jLWo~4$<$*Y%75S1#0hwd%E)s}WEKI8Skv;tH6 z`O)eF%pX66w}}Cf>OpW0`eeYFuQu3RHr(*m5Hum|eAA13;$W?}v6 zQK%l1g6^2(B#lUr7sS_cqT!@^Zhr%^`;TDU3(0-QZT}Jz zsX)Ciy3=syFmn5KZlxU+nOTI^@I?M#0BA89QwkE}C0Y4aSUHI~F9wY6q3!Dki+YeL z9(go~6+To(Y2p#DVd?rcsjYsn2c@oNe=T%O)(hjQar_>VZ;wU8umc-CrtAB%xPimj_%lG=_dwYoV z=pJh$EPwQcGlOtecdC3%s4;juHo(bhzgE9fNgG#WT=>>diGRzm8rQRN8&|z1@gI{&{d!=?Ee?&f1sIp^mHRmwUm^*krDQLd3uKR-7MB#@jp9Zfq zRu62Unwl!F9{cX>$EuKY`&E|xA|7K=@mN%YybJ`p%cP*4GZh+2U%SShdNt{gQ-~7B ze7B1DxxVH`%nCvs)DnFHmFpe*qd#%~Mx4i|;~buQs+&q1PX-jR&nkiUD??nXzf z#z28wRYJ^83e|sl#-_{*^X(CaQpgEtV_pnbFWskw0 z{O2vRJPoVOQHeuVxZX|un>|@g6aB+sh2H z3$AK&oQNm@!+L;DP5bjTdB|h9E?9+Ox2j0{z?2+|`q$iH5G$HwB^1=H685Cn^o5lD#aX{AU*ng}sRR?V;^8N%i*bd%WNo^0dV2JP4Z}!x0 zSj5?8^1trpexce(Vl^t;Up7)D_pRnz6#Z;6d;xAezyx@(iMWB|PpNEJSVDJ)L=Zr> z8zwizHq@QuQdUp^SD=<})X}v83BPP53Ju>eZ<9=07m6+ASdNoC&psD2vcj=o9)6Kr z|7a-8I4=r>MeS2OcA4)#GNUFOOJ^Cy=`UTBxi25nkvgAi%ss%`QlD`$`@d7SHU=tg z2Z+P-cI%FhKCteBfBOT~T{m#$M3zkb>p@+B$rxGs4)ot(2*bu27eIyX8BBG$f11pU z_DskeHd#jHhj?G9P657cJ~ms0n`5`<16T%cMccv+R~lk;kS8v(%Tl~LgmuD>p73Em z>6>Ygqx#k{m}mxVuIqz~^srC(L>kbk#a^@hg%H_h(z%utQjg^yzd=ga{P^Lx9GqM& z8jQg#m~c3II{($(swqptfZ`NmubDGY8`KkxwZ~Pa*Ees64T#)kg8bX&-#wy?*LHW> zt!6iJTrwbi^@7NNnwQs~Y_+tT3^1E+Y6O|gp!G*e#*@Gb897d0i~vx$ko`*BwN~1f zq!g*N@B>qjT3fLA8;+SXn`xYX=!~@pPd){NaY4+V*C{7V;#Fdg%mM|xFk|^wq*M}f35zTU5$^m`P++ zY#y?x7j=`8RxHIpep_9n=^MMuNMpssesv=%s;o zn(}cc7)}w(Vlk!uvoTPGualu#9s>r)>a_ju(m%E$Jl z)}eqekIXa zD)~JykixB5S?WXId;A9?TsJ(}8=sw-K)b`3oSXpey$l}26!D;z+5qZy;ef&jG7K8$e$K0~da4*yFECNUi|#>Px3l`eAkjn9M^ z@MaVQmLktczx&y*miReNkq5F%B5luJTlswhv;b$5(Ww+nM-f@gfze7N}?7t*^Mw7TPlLW)0^`A|q6&Gy%YyWz{3n3sC$o=U z(1T(_baRUa=;WS83DRczJz^e^;9J1EIk&`Z$k|o8clPAu$0W#TT}3Qy~YtHyW4KY;ByF(V<^Cu=rTL2!178X#t(K4Nv$iSz`xI|uZa5OBUC znH^wMdVbla`%84j;L++ic&6uFv`oOc^%*2OmwGjsG1hK4E)4tULgDI8`zEiwPu3hW zW(cRE7uxyzq?vnkY}N8;AI@PZ^(`;!m%$8vUhHvJ(ASp2sbh7abLM|P-FqeP9&vX^ zp(bG{U`h#q|evC8ox^O8UKXKb?7>5JS~+ahWmK!sJp$I+rZtN)Tgx2|c{hA;G7A7+9^1n{vw%c@ z82tQs?SxXclPzRF@}ha)yCTmv)V=q)>V<-loz#i?Swcfb#B9t#$q`54XkU^o!1qM) zDMqeJm_0KpY_%q8p#Jq}H|?)(t{c039YxR({8BLdv2?Lr$MOat> zMfv^pek{dP>=_0pv0m=E{rJq0pVkGh-9`lj|H(W>Z@sau`oo3&<9$htF(n?Fs{SB8 zy5M2=$rQ=e3Ak$ZD1qyqpwmyS4bHxPjB}gTxaMRk;(yKct_q zSR|rC8~n-t`k;UPTO~S7^qJI1t_BZ62g2WSmfo6Hz4N&69;D8ftnw*B_G)xmmafNc zA$RF`bR51FGi92!)^@R)<+BKzZnd}A>E_WWJrmHp_mi$-Bjs_x7b{k5O~y<>2Y9zW ze|Lawmku!V{9@+XFhLs5$TWgIN5%D+bV&8Z_ft{#dYV88J-Ssq>5o&5=>0Frc{E6R z1z}d7(e}SLGhO<%W*b=Z=3-JCZ%@~OGr-wzCyH-De=_es2i;e5?|ovd0JAp< zN~6c3aQDV&e03Z1=OxvowuUXeo_gA)M1_X~&ZXE+)Hp|svcdhSt=0lwlgpMPtKu9X zpC{Gll6FErcX0Qf9UIUn6E@Yq)S-l2nu=kn#-O zaD8mcviGbvP79=0I03@slLKySRG}JMz`l`q<4b#E+C_xLi0;~n&Cu?NWNe-6C(E!* zMaG5R#7cn$=}p{ZRtddYe%;O?m5s);cYym@ddofO zK5L&q>zUF@j%{k(KRYkXVau8|_HdP({69r3ia!)pOnDl)CXm`khsT8R+3hnUU;Uot zhHOLv1IElti=^d&A2V#98_V_HPK zk(H;^QrQ2`&Gm|8EV#c9rL-!k0of6B9aFN1XM0T3az{Ix4$i=Z2P{lRr zA3+jjRAHV3a20nu2h88wcouaD?EbC}GBK}=8xao4EJocZ%v+_f8eCkH#nm5DxProOJ#JRs<)bh78<1jLp(w3>P zr*kb=H6m~Vv`j>gfUXsk4ZA>PXNj&%?mt?l@rNvqn3-IVpGE67PL`X(`^7WKySUqNL{R7@$@}KDk{M~Lwz@A-}6DCAh#GNE?p#`?gs0Y_i zj-Pt1S=HDVL3Uf25m80y>-SpyCt*=lmeb}VE;E5mN+pbsakR$cmSw<|S|8jYefqfs zUdT8+Rp$pA^fI~?HZi1jgT0i~JTj*r_cZ{cOWPs(sU(ssP?BDhw?Y6{KpdqYvsP*& z@!dPAX^a%9Av_?QXu?57CVfr_0l{$4zB#Y53(9GnF&IOca!H?mVx1gWEgyfGfqlJG&?l4hlfv)f>rmdzNeT0Btt( zCs@*zpk2InxU^U|fbDZ2^L7STgx*?Ba7sOGhgsv_YK-CrH_91TgLc$<%NRbTbjJ|n zqP0bhrc@bcOPy(ZBh7H){?G78tnx#>ci`20!n;q3bW=Y5$-_@2K~<>;@h#ncOqP7@JHc&?uk3YU;2Z`Sa-Puc?nJ*>r#x zTVjk{;3IxGAZdH;MZXeeXRw#q`@^1-A!!3hmYs%C_O_LLZ(M3P_)9EZRz%u{`#Lm* z5bblIJ(eu+I$&dosGY%G+qgCP{}nMNp%&)z&;+4!cze*Y4 z1qT#*lP<6<8$_S!#FMQo*@m@_F-QAK&Vwhq!ZVybQ=Q(EUCQw9e`2=dlmv#H8^kd# zmH$lrVoX|W7F}74?z6RwLUR7o{w^6gsj7i4y$3lwe~C)_SY*FstrX5Z5ohZ2C7(XX z2JpE_szZgBQU5M4) znitkhQ$k*ZM%uDtyxa6As;_YMhN?3PIIxdbO8)AQ(d1DW4RJzvw^rM>9$!i9Bs@WD zWn1N z`R2@XQn0YPyw`PGMKPd+59frbZ@ieb#@gcFD&cJ=F76h5r9^OOmU3PmlU8k9Wiqri z&Noh@5mKGNR#01LfoyyF5F`N+eCYZx9z3%xx z$MP1_YgX-bsY72a686<46@CBu+ifmCSN1o4dJa`!H!#p)$gQ&!u@c5&{NPT+61=DG zxa?>V+$CSTS!ns?IQ3&Aqn5y^9rN{n;vUQf0+5_2T$%7}&Fq;cuhwkU8caNO zI>g`VS1WL|0pR2Y7>9WjGreJ4w$!FKxcNom|8GbfyWl^rLfS_9iH%pS^G%!D8(UVP z04^%_dR@h&y5w=x!*gJT6{`Gl#!gzR5S36e=Sw{89{XHq5+g+Im}~e)ETJ~xX8FX9 zpmk1TonTB3yAAFuDnBuPWhy;IKV*4FYPRe;cmK#q;%o@uKtC}tBeNE%)zsqQgI-h) zDs`}G!C3Ranq%BG;o)QCBgcg>(+@zdO>puZ{^HiRcV{Z9+3ok|kY!iFxn+I%r>P?v zSnl!Yit&uC4kO@c`iP=YzTrysk)`vbXq?IeboZe`^4GcYGnXdr5+|!}{S)>J#-vWK zX7cTDMR4FaWE|=whI)?)d=VntP&T=;4UQXAIARk|dj9u=gtx(8sgAuG6q|dqAXq?( zHWxd}@TD0UQ7&}kB$K&>?-e;)%evv{pQY*d)u3<0Ww?$It%0?xF!^_9zchn(Ej5$= zTc*rpO5eEO@qlsaRxo>CVH%_QHt9}6Oe5brW7oB5jaJy#+iKiU?zHYd?nLC81{?d$ zo?DXvKC?t;`@Npa*#SMZkc|s-%;02u%54Q(2ct0?EUX1+bpx1d-Em?}F~95zX9kuv zeaGn&fn&5E=*YJX_^LckX*GN3qH8Y5y{e#LSz;CIrx9MjDiH)xA1A1851Omw4A#=E zLsh3Wt^)t1<^9ZLBV!<{<_JXx$_u^?PyhZo4fmP~qse@y48584XlW7`;~eG}(pnp4 z81R$fPieIHQsQ#o*a5aDb8lG>3;{NmNI!-<7nVkkFG91H9^54$36zlgoL7T=h*bSE zTEyaKRSwfT(}}|sjWdLw;#ip;h#IZ_Zg1m;KU)oQA&cwh&JMg73DHylM%6L3?uE*g z*f)>=GVF!#y9WYpuCA4}m;(_RA*W-GEDE0AwV=Vev2pHS3MjC_U9Bz^el4gJp~j7i zP4=qu!ky65)>pwAK;$`tu2M#hCGcI7D-85a~#xxigO_$ zb^Bp&*K&5peyZETd7b1>>7`w|RS~nU&I9at+Ex3Zyvi^rq5^i(KYe4jI{z&3gAl1_ z>mIP2|LuIK!Sb8tu}kbK7ceIfblAa{kUP&CnVoDT7BhCQ6xptkV1?! z1>5Q874y#Nh6?lRpUhy0y4a5#j5EDKaYjt+=dK)RX>iPGe7h9AEw5(%8LOBgrYuX0 zGA;gS=3%;Q>;Yml*kM-R=@pt3B|suj$uUOl^_o`-w=EohhuFf}y_z}=;j$$Sba>NS zNPMcWkh%d6*j7q2oM|0cQK3s|VH_yuN5o>wKFIc^SUI#E@^6Dtl*!d|m~L~+8z-rh z(WZ|UW(qri@gBus#%?8s-AO{mud1_q|L&=nWM{LHYdyrneIaY5w%~!)z*rt#euzy-X z3HBicwrl}Q7hVp0Bes#>82sadNZz!bkC(4ZJx%y&gCUv!oBJt4C^mdV@8mvD zj2p!tci+T5e0rOp{UG96yjYWU2YpiR5|UoO8O$o!VoUnDmOiSJ%u^~Reu2tHRWOov zQ0x-WN0^y}z(lyIQFm(7Cgs!}BRfcad|p!=6S2WMsbSk9`TE%d%J4jaIrv^{Uf@J) z?p)PJ8DE1%?MBp0S=QQ33(}g$3vd^Hu6M!e{mef!m&hzNgiDs3Leq^^$fqm1RK1Vi zTsHYNxf~4}kMjG?7(;B;r{gi@2%-jv zc}7M+Yvo0x;tE*5AVRq0r$k?NpnVb)Z@9<1P~h+|AboxkaGe%z4LrE`5e66*oXS16 zsg2gGxjZdIX6Q`fuRT^@`k(Pjga7~W`^-vS^jeEQdnV6muy9|Xdh`ovhkw50eyd*= ze{-#FEJ~%)+8TOwqafs2%n>-_8?j&13T%_TR5V(DCG%510TY+54Wgw&d=Es~Hbp&K z$Xz!iJ;10fh3C}2WZDDTbr!Em<4s1Ze6^Z-+zK^^8^89pB>BC&8RQjgRCvfP+}xf1 zSEB}nt3Rc~AA0U=OCG7eb%=jH${6b@7Xo(__e!z0pzvhjG;0wdJXi6TDmVbemBry?vPT{{0@`eN}Y{lU3)Ml!3aoau2O59e-uR)O>~G9lR{AI*(gAjZ$r#yJ8^r?tlk-uqJXMVa)dpDT@TV+ z*MLF*wL(~lzP#Q}!1R7r8GF#-^?=_iZ7pQ&E`(2luq2^XCT`&DmA zKT~$h_fb%y#24pC9;1uGqwqag=D^vvXKO^O?<*CJLrE#4N_kc)IWr6b&u``TL zPqgiI{$uM2=H3{eul{L>%iuzFe#c{2{jhxY&@gz&H^+GI%EJDQmQe0mE~%K9vU%x8 z#;$g-gY(Fx?rE2d;nk7yo2mV*AUf3SnF|iaM-Q0Bid@Dld*$>Nl&T^m>nd5*o2Th` zqGn_UP%V1EEvn>6jcpN22rNS>ApG~3OgXcVi0RZwh&@esc&HTLdK0nalh3b>-CSYJ zy|cS}vn3Ro2BX#YIXM_@I*fi@bLw`L&3`loF7IXeG(Ro4|IV6)0x+GVAIC6-_vDwR zLtV70RO4(bgN)NOx*r?<+DehV9Zrv97z<^8&SbFM()fAJ>c$SV0^&^axD%PFw|{6VP0TWJ5d%2 z%Zs)A3El{Jthm;K(^|MCiMXR+%QaV*3XF!VtxhEv#ew?cq$cpUd){g)ev8l232yN# z=O9`mZfT9AhbuDB_NKP$2MYZU{*5nqv!He|77H=oK=>*X<^GhZBGonQ>FzemltZ+eavL!SH0G_zpGkDZnndS8LkC%(uuFB*SL^k(p zyb`;Au<;l@+|zi8;ipqUtI_9!sUl2mjbVkjYVMGn8FeK-vvurq zVrH`qfTHX$dQ0vtn>UuDJGbu6c6R6&=Yg5rA5m15GU!(#b{~0u43ta5Iiti7*F?8O*iVrXH^=esx|XOEzRO<+wChAN0RrO_RoZUmy8XWU+H%2m zuIz_c#D>p=f66yOh8d%`#br@BPT>hRs9G^FG$Zy7zEyS3r_82%%Ruu=5=gb*7?u-V zqatXIX3_|RS!c%oi+a(?m#fcHw@;GXetc7WB71V8GAL?%f4sx-z0WMDw`Co98yvgM z(4DP?ZCvvW9nwaHtg3N%d2`Nga$a0&2bB&?hDQ(fRb}tb0zZPUa*rz-9@2BLnYxi!d1F z9LjFEQfKq7-6SVw%8!kE7oZTam#pMMg&FCxPJg>=J8T;}Zn|=u4yS?ns&wH%#~Nyu ze~8?+D%L3qU0reX`(U;mu3MohLr;fseD)RPCbARB4$dHk81!EdueLSaXzA4rKSA`W zZc}AHa#$@384NON2WckT*u6v3G8|Z(gVe~mS z-UPR-4>UVJ@mNepvH%I{)D||%4$VB|`5z7yLE3B%ICHZWs>`->>tbSaS=vwk8WayV zI^KCD^e}h!0+CDiXVqss=z=6=YxaFw7JsE)a?$9TDTuF@MO8JMs3Wf{hi-+MyBXdC ztSG%qul(WOx`K%uE;35&bc9z_z|4T@7yz^j8fOu659yO*UYUQca;jiM%OsdZAHcHU zmpxA(3wsGk{7wI1(E$rDGsLKr9|EI}*Texq|EfX4ef)n5wlW?D2EQ4ZjHKH?rU9yk^7XzumzmiqOV3}D&?449>bZLq8N>otf zZnEU4-=cV!AN4w=FA4tk86fAG}Gp*WO*@y~OE zPH$j<0{ikAl(Es$950Tn^BV}3mVBWNY<8_t!*Ty+R6srLh`GHw{E4-`_g)KP3!DvW zV;47CLtr5u@#j8PB6>B4oD}~M)^4AuFq+srbZ3X%4M!7}1HS~l=VX!zUAnrZD*m~{ zYN5j-B{nhUfDu;fDZf6?XTRI7alMQx%{mR!+l=0Qo0 zHl)v0sjt_9SE83|i6*qlZ#h%d(U4ihH>brIZ>r3*h7(4oqvJCsZ;M*7nz)b`U;lms zEvdJghZi)NV8tUP=+XR;3DJW+sY}km$(bi7x?g%%a=xcDf0Vmh)0Nlm>Uc<`O3XchX;OQAf*Y+p-T;qdTosz zlFBznzrVt_5faDtepINz9U54r|63QiVCtMfH_#nuL_FvdU?;7hS07oOC_nhzWU3&h zzzxt1ee25_+xr-V z)`S8)r}3S1?rS|OAvR8##zRW~5}^x_hwN7F`4dTPn!3;rjELZs3tCdF@MdbN#F1A2 zqt0ftKmjt?uD2R=%1ZOY*6?@Z6MmOG_3~c3zyrmt$!i#7@Jt zsOOG5`eVHsS5siM=0+3`;Xr{#5XTprj#rKBCl`MF!ZdZ0Bben8IGDib&l5ZWeFiP zMG7-~D|sv_(dHb)7rLOPYe$Wn4zwvL0AAK{J&GP9GfdbWU+A4$+v2w2l|Nf8+FVI^ zJ75(=Rn(| zB{cZfms`bDvg!$(qymE{E6gr>oG{qi{Okk>*yj4C@NwCM`Y*^gp|(Efkx95^1MX0t zQ3mbDDK>{l6`J{$@TIVdhvXabv;U2URj^xKBxYXb!sy(?8MnIG7gl9wg~w}50ml#b zereqp2^liYt?S)SX7Q`t~38%q5(TQ;7x78 zVr^=c9-bA6|F>}e!MW5#PTV`i?{N(Nl$}2`v&G;}iZvGT0GEo)F}QOZO#9+uZxVBF zA(cR3G3J^ajU0Zoc-sAau%&WaiQ75qdFC1N??j8kj5L~}%CWM&o+x!^pQ6^IL)t=X z2{yR*iU3J7;N9vIyJp!3a^Dp^=6a#`uSSHa zhwN@HvI%3P-;uEd;oot1YnLrX$~wK@C+PfTZSYhgV=!2~01Amc>qNQ7CP?A2*QR%V z&bB-Hto^N{(7BO8D|7<5n4)tEsmCU?HF!`{!R3kTX#<^OW?Mw`J)31Wqi*7b-P(sm z3GGro@FB@FUaQq7ndYIoe3lv%TVXbCzAQxSP!{R_*b`&u8SjNJ^N7WL+@)I3x?KSd z*Z`}}nuSq#>|?VDI;!FMJM9%}4&yVf+Gq~s?w8(B|NNf1a{Gbm?7}Yd+1lSHtVShc z8y9Qr7eXdt^LAu>$CyXDMOVDxJ%GT_s&s>;y9s(6047*e=A?wS1}y;#3-9$F{Xzdo zMzY7ms?{#x6>^Bzg^N0qdLU9&GMhso`pg;}qIRr2ik&S#;Vb8`4Vx}WU;f#Zd%Loz zS~4(ksmN_(0w}ClOHsm`n-hhzV>sIH3Ix>Ekk{{cg7x`2>-?W4-&Z~l)$o7keG!g$ zs0*hZI(rf8AkVuEGb{74{`t(3qENts$2*3qqvH+Y6=yO7Q}9Y4qxL;Lf9RxxuO?H80i!rypvIakXdmyBAi+n0>4wFdW=5*_XB);F>QJ~X=A<+SW)(dvVV z;LB{gc!`TzGxMqXeVsA098^EA_VGGgg~X|EYcgi@*D5#PL2>ndT>#doqlhECm%&(t zaVDiHLdInLijP`Z(mmC(5U*2Khnl@Q*20d1g%Zn7yLW|=l|;OdE!v)4)FrZJA%>X6 zQF+v!tIq2E+>xv$d3EZIh5x8}g8jtxtQ#jnX`2c$Cv`PZRv$hv&?v7mcCB?`nwSiy zJmC+osAHGGoImiVLvWxIrFhE`78V2^eh&^B%b=wH#|_!00l$$qggG*~-C-f(b-05e z`IBjrVAjpwRwlA@t4$_J4H?cz;BCA+<2t!oH)!MCYWuZ%ci!*F#ZNmS{p>wwVvl|I z2P2OQgRnAP%M*Oz}>m{j4u2R|h@bd>OKHAiTNNU*%g1+w1$esIgQ( zn*4i*J=C=+kvDZ0Eod-lBtD_Z#pafUjsAivYyiG;?i7DG6ioNE>}*MqqW>nE_mu*^ zAAb|>V8Z;@96zEHbI*E|g5uaD!^X;K?bkFr1nROw7wdwS13~5^@s9OFKb*q)qcx%e z+?g7A2Y(KyhRINjxm{})YsJz%wAZwX!RTG7g2bR0B<5@*mg;`ef1DXq=$>e+p8X|o zJiX>xycPFdox)I?ie-GYF{0J5!zPGkKI?bU-BI!^j*90#nLg06*+g>#X0qqxN-bY7 zY>FH$>pVnfJH{PAp%dAP-Ae2oc6W2sK*Nzu`|=yH7MZrowrq%5c-&lUXzyg*U#ikX zrz2A_;~5ujl9(|MlVfE+=?{8}w%AOX!gFdv!6Fjtp|-iT7Y!*JuBcC1TezofJ||2k zyH6w)RcNO_7_*u|fhx{T2tYVxqDzTrovzkokEGV)lJUF6>`?c|kWyGhIn*KJ;gjH% zKk<3a*&%ut8UG? zH-%0~hVwI*qw|yLKTlyb+xKk*t#2n2hTw}PLrgPP*kJUP3huyFmw?{#69F^StwI}^ zq{jQ+BJAt-`JHckgED~%Y~R~LX2w2(FBV%-2_2Y|_X}ECPQ)JZ@2dJ;WJ%q^)t7Ey z9D7Pq?49|YVbK*mE4YT!EaQ)Eyi@XSwvzmhrZH4kKJou*8p8tJe-zu66ApXs+`<1t z-EVdwzb-c?hX6{>rv-lb$bLV3cU#|PKhbfkqJ6yFM!Ff;BXMFZjL>|DS zPL}MAT+PoKZ?TsF`Q5jygt(`nK2+OrZ#Qh5RWRJ&8g+Uj?eIhO2kqg%yZELA_;&~Y zvVvJwAXPF#^-mZ9fB5kyZYfTCR$yNZz*RWJ+;&^Q)OEPc98kJ9@t*-}5cX?_{V+zO zGU$^6)Aoh#Wm-@sCji{cU*bB`Uj+~7Ztf~I2Mk7HZ|YIvsV`!hcv~1;*~?mG!*Lj` zzy%YoXHnyJ*72;an1DSUuMnYGjAA}QZ5sJle@w8vQFfMnf#9;9R5p zlw!my6~NC|J{dAQoM~=qn}+{g_M4?bqQ)X>l_R4X*E z=brGIx%pHqq%4zg>gTUxZOYK{o%%O4YlDScZhJXWF- zQ;|vX=%)s0*pN_vxiW$OGN1~A4kw)zpGb)69Qu!hAdRv;Q7NOx7RYMa$EW0{U+BL)%&E6^EH~)h(QTf0ok(GNcz_rCT21p#5~WC~1!@7t$-rz;rp_vgrB9#58L*MsjO&=_1d-<5$IP;gH@_y1}RY}&p$QCNCc-*A*yKix{!%{ zZE}xCxXLzn&m!e*!1egmi}5AX*;NrH-Qy@n>^lr(yThBLuvR{w7Jj1ASS5e)>E%k6 zr`r1S4`zzd7jM!{HbI~e^JSTYFzcD*Mc^6Q@F>Z>WnueTQbnqLd{&>K)uRWiF{RBR zPdR*9`Zo6IXZ+(4v4QIGR6NB$0q1|7jo{P)T>tb5U!o3!OL$0Dw0zs;`7;{f)w-oe zvtjsD`w8>>JTBq4BAr`RH-aa=4!NZOjQ2CEzmXyn$GqaTNBakhTw!v3h8I34zT4Sp z65>0ptRiV&be!j@5}#kt?go`-%~qe!R$iwYv53un7A2FD(OaO?fmz2UduIUC9;L*7 zt4=Wee&DaWGT-gb^HeW9v?>dl0v%eqq~%p3?TKJ0u$Ae{7Z<-KTrX{rYJmA`PIdpd z?5uef2X;>=ACC*8!puk_qKW!VnP3dA1!49nJ+JU%beZzhGxTDC?W=BX zK7Y2>dBP(?ttlvr^*Nf(l*Dl*Kh{2EB=f{a(`=&%+i9+!g3wWHftPZ|Hfj;K`~vSA z(=Q$z-fa6XBNk+QQi6n8dQ3?U5jZC{o&@i9w6`zJ>w)F1ucRWli|dsf0b@eC10;Qn zC9+&AwZE26>%zI0j;*8>6%qrI^of)hpwo(rWp{;nWmI#yM%&;qjbI4Pcu8N0`+@Fl zp^HqL$v0W)p2VQL_PGVJ_96WWX|if7p*mH?tpV&N?(YvMMH`)men)Wg6Hjjz?CdD{ zb6L0Lb@cttn+L{Pzq<0(mtNwQlvA_S9CrjK#7Hf^d#u_yASvvP-39R=24KNIU}3l> z{NTH+x4u@HGN3HIf%YZIl&$U%O4}-_;ao-W%;vxKexpIbKz&ED@VmoX<-udm8=LD> z82zy<-Q8fmt?fUoxRYZkIahDaPUb76jY3MDFLy{Ut7)I6GoY25M!1}&Fk9U9h*dRb z^uRkE$O@mcJHSSWLBK#_L~md z&AXY?Gc;&+C}AZb?r{y@E~h*x*QPW@s7;lj1^rX{G7nV+NgG3}6_}Bq#gINR>r1%Q zWJv)jU|Y50;P~H-D5ZQYOZzW|ocGQdN4a+zdOohM1DnZSAEy|YmaF0W-#Jf+I0xAp zZ^}*zRIwK0k%%`RgPRhV^mnYP-^)V*Cv|@8)TKS`^L)^aN>g9+MTAYXg2N1M-02ya zsz$`N4 zEb*+#YD3{GrOk#m?yIN!o0t&uGk%IYoTTJ++6D#PTPellwU1nGsfIg<%7#C-V_k0};N4)fu^O-RmN+5u z$@(;VzvZXP;L{!R<0%nX34=@iSqbU0$L80VJmfj+{%5v!n z7;9(o+6~Or#oE&^n6ot>^UWVF@nS{~<$1OKi4nWtKk?X+S43d4L*PVl16_sn#y=H` zAgT>HE&0Snyo_0BLpOYuRuUD2t@14<^DhHI%E6jOguKWg^YB8YcF!6{#_+%{|OS2*sbxLHX$(yfE&^4D0=Njd#xR+M^BT$R9 zkTPrA64!~Ca|#hN2+poXwl&y_4Bem-?_x{;j^SQrP?Ey;-AY0v2kh{ z?u4_s{B3j1S>-N|_$f&vmjPqIIz)tMLAU>Lo&41tw;g)q5jgxm^S{hL7?+QDJ+%>V z+k$j#>!N8Bqfz5(%UP|}bpZk4YvC{N%BuMY$<*A6zSs#_6-S?(>k#V=&?Im`u z@OXZkg|^B@5YncJl&+u1E35Eyu5xCIly}U;H-?N{&^rm8XBF zFBnmpT0X&ZiC@yBeCYZA0_=F#du1IMoALLGV+FS;W_ zo8QW9Xhf^As^CYxlD47d`3j6POdAqqp|o#6ek5?4;qsT9BPZ;8<4R96C&NE%C`IfV zJL%Egd!0A9cxFez=H8ihm@jHN%X9h5|E9&YteXwR z3BvU_df+rlW3MK&;vSU+SqEhyWvvES`StreJV=Hl!{UCXpjcU%nia8p7`+ZO-Q!+) z3{MRk9p_J5|BhEt4jhmsNJA4RQ~{xD3Q^skB9re~IY={0NH5C>eP|nNF~2!oa^Wz3 z3nJWH%hCadQ9QrKhgXzngm@b;e9Wm~A%GoJ`g&ESA%VXS>o(ZpWk;$&G6MS!^Z2-d z-Mq%}sLJ<-22Dy+jvAutOI`W8G6Kj30aWBSXHiUT(}8C7lC&A_WV_373Bh0&`Cn`0 zzkHX6mic^#5k5t-2nt)y`hwqS&uMfCU%aQaWLYoS)dU**s0xlHXnh3%+e*>BZ3Tq8 zc^)dXogt<-72%oenvVZa^DB{04Cq|!fZx4-Qo@S4#K1>hO#k;By%uLN;$tPx7&v!m ztg18Q=~5vA2`#*`!#U_?rJ5#`<`ymf-Vk@QvR=8?FB8-drG-`8Ey7Tgc*EuGUCPUo zjE?FXGfz+H`?VCNTDBRm z_Ij74KWnR7-SAD}Gnx4cC}t9SdOY9oe&1_)Q6Bw608-EL2xS>SF0fwsvY)94&z+(i zBlg8)NepOZv>#M{?{U-ICd5Td^k|UDII3OLiL;cg)un&_!{==*np}W(9j8@lJ?DEi z;vN_;HLY61uR1y;h0ItVU5}Z!95XW^Jo|%`G1yL-U6j}?WdQI9Zg6H)(1i!2EO^s* z=M7C}Si=o&gC_%^4PQB+jU=;70_(yiW4j~wROh1rnH8_&^3ZJN@3ChJBf=+|GUi{U z!^NBKUdy2Pd<2@4)5e)5YGvDU_T)N?Sr;Pff>sZ%9LuVwC zi9O)p2C0#zx&PCBXw>iiXs*KQWho4YwGk?CUv9d1B6e@wKVkXt>vNFSr?fmk?O6!N zF3(WKu_rPAACR9=Na~)+?AD5^T@v zjj1|b^^Px@h-&434SKm`uM1?rMj6e>bumeKp*TgX5*lBFDj;hJcAPF$x+&$!7g$cN zd1#U3iL@hPmll~lcDAwDN}i#UMG9?EcIeu&*^=okp7JG0y97$bGeZv0L~g z(j0iUh7Msq!;^808qNc!h+&Z)#;B*=mRwggmXT#~_%Y%^KXlbG>t`spf$)`gH|zm* zyX_9{#qIOwH-!z{@YgE!i7LyR@*$`G#T_8i%j^IuY+7VIV|Jjigm3L^DXDI9HKq5| zo!bMQ(zBCkew#D4Sakc+JdY>{xcJ0RcQ zbxGgn8+~d0%4=ApDkQYBi);LIA&OeRXJbgX0Ey)Ss9P?w0*mTN@!7?Kr z2n=S$WCo4ERVnEn%j=O}`j_{E&d=|T*4{-OMU#OGBE$rCa2O=Hgv(~RZPK)PZMd6~ zL_|qzo27=Lbja?qKm4d9$iZW(wd*8>OS8Ihx@jjRgP<&MNHGd+-Dro0Er@<^4D}yq zO2#zupst%v_x<#YjeaW|$90y2j+EYu`U@cBE zQ8>-Gl9>iXW=Ubp{gcGCL=k>+E?aJ7pxh*(YCqy-*xRPg2z4v7L~|20gGTVrppHg1 z&tB^n97`nK)?5CytKta57UTOkQoAAI*So~y^JR|rmFtYuMy_>0D3V%YMSKNX!K(OA z6NWz}T}$L=8bKWs0#sdc0hE55M&+suj+&vP0(@g1xcS;oPJ8z(f(+l3(j&`Kjr>37 zJ~%&WdjRbhu{?T!U?rh)nJ1L9X+o^e< zU-Mbm(UU+y zT(_a=U@81-i-j!o?(07vIDd4T`m2JTR2IIqxF@SIPv(_yzey=&e}6Sib8Rr=Y|^Hl zk538_?@oubL6wwn2F}9ht1fDIYuV}L?pz}Gs!ZV`z;r!JeKcLc(#AW`PbC)bWB(BT zA;6I>=9e3~bZ^k$GpBU1VfSE41q-=WR8YGC1fZzIaY zw@R5n-vKO5V=HPguT|8Ik@<)GA2saA1LzjUkwg69u)S6V?>oc$l^h@bs7AKM(l5NL35 z&X}D89_@^wgnXnrJ>doyYre^$KgPo`djCX!w>QZVtQp_IFo>Ub4UA0wI1x>>GIO4$(p?- zs->w>-L6^6`ILS;eVFfzxglr&8h@n4U}F(3TT$PoxxULpM9bG+--qGjWP%AlVuFyV zn~^d&a;!Eo&uIc`3rx%NF3ZKKO19fA*zLFxRnA#xi0E5PqfbEMU4pAt3^vKuKL1a)F2#HjWbB~VZ}@lZ+7{>- zo=xkyizG5P*o$9ZWlqIB<8R%Dd5N!b7l$kv9{s*-Kf=fe33(R#tLn#=rbAPw|vJ(u=I5 zKYjJ`B`Jc6xJ<-w8R6E0V6xy zz1y!^IvW_H)XNF5PHAbRDAHcErS{@Z zb|Xz+Nq2*XhF}99WidmV*RU$wx6RvSYTH;gRh!NDC3^9ptZqWRS8D033j&|Yk%=(Drv!((b7c5{ z2w^Bdm@y-uXi_L5?7Gaf==PXBZ(WLg7^b#+IqO};%P?O9pst`LCQ6JL_1Ljmo?Dxu zCp=f)bjyHuvpFP0>;4BC;s6BGS6`1)5q0VNnyDn(LnD=_jTaHuWxI4nyzyU3fzIt{ zw;v!mxXM!V$lqSGe}Mb4U#`V06Vwll!TPaERoq-Y2+vei=x(^)w0J8G&iAxU{V?57dCbm0&MaoXJ zef8!uR=dw#@-L4QMIij0maUz_j|YTA_FZ<&xz3BUieyoR+fzST>N7egzm|-5GL#iOLe9XiMXuAW90P6fm6li1bNm`o9N%KQv6{Kl_>f06Q1POE?#mbnI+ zH76;%vg{c*h;P>sJN4hd1LD#6iT`X@fiUzV5^Ez!ttw=!@rDbn?qm=K7B^;r9$*X( zxLtvyL@MDO;G^Y?{RXS!G5Wj5E+xTl)B? zcR36|Rd4Y7!SdR1q1V_;C(bQHTHBX`HY7VyzK-2Kk+|63@VKYdT8%KEOk*n1 zF;$uye`|0SHk0^@NNjs^@AM2uWBEj5aku|m3m{w<$Z39?&}}s6N`j05mUO; z8X94d_SOhJza~N`bxgkk@h`(Q>S zBqAos@GI;{gQaQM&d?6i#eWTXY(lAaGkbOJ0&rFycu%>^2kkF=AL#>f5PAK)|6?<= zg4)xRR@r^GD0R9@Hs;HsL2?WRkgj0|axqpI-|;XhPp4xjFsNj!aJlLdaB-U!q?1JDlvr3r;^PR9uszDdBe0AYRU(F`T*|il% zE?{Z9WHsA9f`+JjjyIZ44Or2FsEX-{9g7 z;)0!4kBs4eb2gWgH+3I5$AQK^ zAC1Z9i$U^&rvTq!j(zk`)Sid`s~y`brkh`ndh4T zQ*nD~AD?I1`%I>1*)ek``E@!VSQPE&EO`#Ko%f#4?#XL-hf=mrSsbC7Nihm0bryJ& zb!tFWTLS0sa^m^}ijmd7ej9DIg!WuBqd6U=vDv3tZ{=ERRaC~p5@U`m9(#nYNqs|G zeN!jTZrr&nA15{(=1qvYnYZpW)-?q?F@D?R9+{ER!zETY^csB{a!(|7wMh!dv)H%C zGqahRN7pL6FU{eym#2IIZO{vE3d3kq&mbyduv8F)mejhv%dKsw6x$lwD}{y!i;^DB zq9`KKS&#fl2uG2OTVm3x0)-b72S?Yo8}n|j2-v!#yJ-U)a|-SJAPu{J=1cv1@-?JE zgA0d67zZhjpvDrUKFF`QOkSuXQWP!plZRjN%*QMG`9H-5?3HZ^PKtFXDc{Qf7XEyB z2rE1>@WfaWi8y+d%nQ+t;C!stqD|ncx3V->?Xk&=YdO5fdiaHz!r+CIwAMr8{!Tr1 zkp{{lI40B?m;jItZV%fwxp?f6tvVHo51#v+zDEBf=CJGlh< zq)>QoF4vxRNqZ3A$$cCjmq262DU-F$q0fN>2ViP}Fc7#L{F-n2pb4&5Ocn_eRFs7` zvsQQbSCR(4Thr2$KqcDto|9>&gO)4rbC!3NeaVC<{~Ot79+JSi`7lfwcM(dD!F#Yb zyq&W|DIW@GYH#&Fp*ArF{orL`?G=}C=z~Xb-oG?#n-AM?Egp>GlzXP{B84{dC8m?` zy__hM(#(G;UpJ>&0eXj1;cQbef{c={R$#9u)@JLj>IFT5-gw5aoi@hEt3e6&olle2 zPIgQRYfqTW!nfh7ZqDcy+f2yu>U@dTX3lER0LL`VW5-Gq{|K|k_Sq5)`o1sQkoZ#v znUB%^)^5A-V!H?6nF6S_3d5K?go>w$FUd$kp(-<9abw{)zu?Hbek8!++g^Q1i9z{C zOT!Tc1XFkhd4aMbFHnK|JXC$w5`MmG|0PoUIm zi4mCtDcXoq{4|%oKNP#4)?x=FYv+vog0sQOl$Y?Zvi{X##>!ips~A$9oL>qJh}<}A zKzjJ3VfCodkVbQdLbrLea*(zkWvYhuJ~^gN)3oev43|PG?bwCBk2Ctd_ugncUDu02 z;pH(P1irHU!c!xe+dIa@Z=GGY9n9zqGy{Gb%yRc6){TkFgs<{ZE!;-sa+PN1A37Gj zXty^hpao~3)MBRGa|BBxHx8O(t4XD@FK04?HgA)Mk@{m_Ml7z}pb8r4FntuLj+W1m zIbv4`nyz=W72frWo3(Ys=}rzqO%}dX$+&h7qcF)+W}FfEOm=~V1d`2nEbz0?`l8Pgu? z6LtWs9jU(cK`F9<-6+3BC8zEsdee|{!0s{uZ5SAy(xgA{knU6-@>SGQ^}72V{9N>hTCOtH!U$o2;9=I=PlsJ_aT<`bJN zO9=5|GVoiaQJsTaEW*7N7U1vWDgdq(r`DeQ^>y`F8gqC&DmZRDC!X5BR?FwKgZr9C zG|;cO*bW?HJDj;V|Iq!|8z0du?SPwZtR$=O5Cjq#k{4?0yiv@aUe%_vhfejCC0 zL+Qd0#MP4Y9B%^kYdw}KKnwsbzv)Zm}wYc;8%blcXYEld_i z4pdyjZ~{lO0+YjH8SheGMUVltF<~zY+uQ*(d~K#}rp(sc2Al0;wm_-|*Wa!yMUroosz$q9JL) z0%KvjIs=7!l9;tINnKooaj7fBhsN>*F!j)WW}LBA@z=VcE#dmT(pH>rS@QNAjUj&L zZ^X~W^`wz<7U{^e!*;&tAc4?E>J{1$wU801KBLiVyQmcmPH6{vE>A)LUSElm%GuIT zyGUXoc)Q`4Ha5PEiGHvS?=apw)@gKm&{6N|Zkjc z(@f$)RND3KxHcQZv8eK*#8YKOL=Px1bJh<3@;=X74_Lxl&#cU^o2k*=yBBSN+!<4d z%CpC>l%AS401?-ZzYVIv%w;H}VI>YSb$=YOFci4sBfWhxr1EYrrv{Ui=y7C{$o*>` zzmNaAY(nv4rx#VlN`l4L()%qNB+Xuq@gJla<>R8r(Q4{J#=Mc*h7Y|@TKtLs&@f6tk_szKWo3^P7k9)hE-T#> zzj2`V(&? zs2%IpuH|V-P4wlHj(F_u;< zGt;jUcnL!ip%~M($hAxn{krKqo)^Oc?MrNskGGQ+7z!96Wyk)`jc?KnOv!S9UIFOzGyd+db%38)c?lsAtwD?fu{b zoj-px6HyobCL2w=tI%Y{@{^Z_IVn4-bRk$uDFyiSguatr&t8d2cF-(+dCxB!l0x9G zHQS9c^}XLQYp}K~6r((?>4&X5Ho2{yw*Ek`e~amk-aj~IC-Zdx4wwSVvX;+-dY=b@ z<}Mr0`1Qri)4!lDCrBVB?@seq$TvO7Tdu;dKFCQo9HNd|Q&wxs3L<>RjiT34BIK`y zm4uaB?}Yowa0KI7#9S21GvW|A%J=FANsGPz&WnrY!)8xSe-D+1$XneNjGiy6!tZnk zZMSZ)a4Ar09Xg^S6i$h{`N@+LH4aCQ=8p1+8Ejz5N?)H_f0Oue# z<(ATnwX1eL->&>LSrcSH3wt;YPJhLQmxrpn=Wht??$8S3x<5YD-vmJZ2YPTooMdO7 z=70^VZ&QWWWKCRE!4+G$CP(aBq1n3V#LG8He!?SN)yV(ViO(mPE4J?xS-)6D=~PdP z0+In`Y}U5<9=O+_g>$Qf!rA-qE!-G=MpY>cIOQ`neWa>KMu`Qs2YwccD5uD{*%72u z<}vZ=md-%y=?%MEGe#*f`-bK>8k`30CgFsz=^Ig9coT4#A8~^ruYrAREpd=H4%g0Z9m-{?N|PSF~`H zLW}kgn4m+mfXxTax@l40zYT%tbLYP`F(l}l`zebfW_-aKn~zLN0%yubZTGoW^dS`_ zpRYGnd($<-mRj=)?={|4b;Vhpa^btqwfsGN;~yOaU{0;>LGxaag#$HuUOi&CtKJij zmbB8V!3NSCt={6TwO9R&9u3zu6I0^vK!&P-hF4zc8l5v@-F*@z3g4_^Urm+asO^X`H!4+c8$5QUuMIR?c}~I#9?Ig z{PV(NJGS>8I64(rTI+($P4+^(PixJKG$`D=KG;Ep=EGWWaAkquJ(S2hT3#y5?LLg|>TUO^o=UZd%Xs^rWTQiYYc8obrRa zdlL1-uC@dxqVD^%&xj<&R%fV^p*Kb;hA;j`)Sl%?};) zCOA8($OP)0_;-tna_yxjscP+T$22vw;}&);UDh|1OjdUgEqE$3q}0d|O7hR3fAq*q z&bC4I)pbXDHGvOxw3lbYfm{Xm!v{JXma8(DKV(SGr_mZK?Lv0CPv%5Xd?d(=1QNly_lr1eQF*1 z;q2Rj@`)e%*iBkjnA!#r%M&^B{zhQo!Di_kT6>-Y8kY9mmzW7*quaBc@^mx+Jz|5$?~?`PT{cm0soeN9FQSCZo?F z1{3v;5MDV!Hr`XvWI7Qmz?7gz-mt{xw{HrHBSAVS3K7!NC#|CI;8tj=*W->j30R}+ z&P9vg&~j?6pNk3x1zx&?8u2glP2u+!)?X=;sv3Ip4hM7dX#wV#t-egUikKl+tY0c9IqUW?Cd zY}_So4LCa3cs;|U4-e8Ltt|F`#$!DCFxK64Y~8obf`T1`o$KwJmdL)qw@^! z6w?jP@*SHdzR2dStO$bHOD?fkc{lD8?@A0F%~b>Z%k>FNrZ74Sr$yn*Xx1c^WOnfN#Ir(klhLwM0F8Q=jpX!Z@F%Eb?P}y)G+jy2*>5r+)p9{GFP2 z>7F&iwv!o)**d9KX?R&Ty4hK}SYb`G|K^Jo=~T%nNVooWML~=j)OpS}+Tbc}zjD+g zL?M!{l`jSN-O>9yYN1ftWZ!a8rV0mg9&eUAaA?xEu3X;OADAz|@yiqzrp6^wX*M0X zaqRo5X`!CpoERbm{m28%6v7eT-q4qsh3ee@^!cBA!P*n@kW{(Lj_sG=)KFi8?rD?= z{4QuyCiZ71vSRWK5GNC64Re z@V|A{8nk^BnNQ7o9oJPv+m|QE!+yY1s8DH#M*Y3si@w_l1X^!k&PrpIthL6a47yEe zJ9=Z6B*nQQ=T4kdcphtF&$%D806m$rdUbbIx1DpI#|}JU(4>9Jrk(ctX$S zX~Re!XbmGh!Ik!4IOologFAukQW@Eudj=Ff9K1GhxNtc!!OF>A$H6?QLYF*lXpNy) z{DeHGRcXEs(deD@M+Il1t~kO$d5RX@^;H<&&@0;4;2fnGd)C+LJMZ6`r1LOGPAH{T zC?XSiE85+z8TXw4 zP0wF8=TpZ-Z`#QJtYt({EThI47Lv9!bi#{RO82$~-XaP2)JinCR{s zHW(9#aIg><@{m`5^{4!Sr>KC<(fJnb^wOx#5Y~|8N3I?U>cO;&;MV-`w=VoV0VoA( z3ABOG!&KkTYj;aNXA99dRrP_S=?V_7GgW)gg1f{yJJ?M9#&bF@`nkC0k5(27_oL35 zLW_yn&;M?vq6OHhi5=426W5+pv5!0$%Yo4azO|x^AcUB&y`(V{qBp4!3w)c=$4!PR z3Dx}DUdyY9uk^T^a&4v?CxJabFGpjOc}0LQe2@{=d(w{bN>T998Tl>Bw*pe?oNQ>_ zzR`@`9FNWR3fDO)w z9Q611LvG;veLI-G#2@#qw$JQM1lbH+8>W38rT^^P%?FfAMTF7uAN;nWiaKriK0JOu7B-tL1}Dkdwahc0Cq6 z^QrZB-J^3h(&gai9&N84qN3Av76f;*F76+;LREJx#S#7N@ON52;@br<TgmbiKj##lq|QjXnY7=E8>hx2iUN>>`QKn|_n%o^07A;mnQgvYQu1-B%vC`e@}Y zVorw_*>zAQe%1$ta7~j!&lO-50lMZ^b^k7y$45Vm%ybpAta+9 za3{#J(tfh`4YO@rPtZVLtk%od&*PkSk=0CV-e}Q^mEB086aca^X8VfVL*Sp9HJ0cj z5%p~PejTD}#m%Py#tF0&OdP?1>#s+SDW#$GC9=pDQH53uZdT-d>2SV|J zv|yvz!|TLH08I5^02d%O?{3rHlB!F8By`1u`Jo6?b}H)#lfieaTz1c?%;fwt;IQtn z>-QnbS*jMOQiAPPVY?wtsQ0VQ*)roHB)<_@urdVH+eYtN#6R=6cqzoDDDHLbT_+WO zkW!H=0Pmum3Y7-b>SML%b*Qx?GT)H_FS4fB(lG_AntnxYq#=1V0dj&F5_TBvLUQ{W z4^UK%X7@rfywOx&h{<BBWoOjj3lYAWVR z=xvwY&x+88!$`pMy`0ZS(G;xv0!}vTuF!fn;#^Q7;E@)_z8R~Z%oE?E1ux=WO7M=< zgMSY4K&V&v6&lbxL&dMMaHDbRu4Q?LCaXa_v5d*rtZ-IV(s(5v#^# zEve2(vAO|t?DN*!`=Ro?1#!B+on_ay7x0tdL)Ilq4RLh_eAW#Aw_v`Rd#eE2OIa@3)N3H-qV!s&kjLka3Ph`o)Aqc7>3?~|1|U>^ zdTm^EH05=1+Q=PAtu{qz;FgnF)cPwJ$$6n_?b5dn zVEw_3k+I*w*nGRRc9A~4etRQ?hV8zqYJJ;is4c27n0!{B&-$Homa20Bj%Su zr<(h=LC@PxTO!Uat%N;Vm7N+*C8-+xJfWqrY~8{piT|zMSA~k!xFBzr*31#rPSlp!aV*fbb|( z<(n!L?xf4;j6-e6B~B3&u z2rhOZUPilw-9v>4YXNxehiSe3424Ck9yJ#1m_{2u7MI9xg@1hK0x_sY;)a-#GL~v+ z=~N6D4O}Yhq6JgDhr{S1sF9#SZo<9nZ*1fojyjxUwKeP+N^ZcvzpehRv3sv*`Gm3( zOsXBmg9!sn>d@2MCGvb!GUq_(q;P$c>s^b1Id#Xwixo1}dci6A%+tC=>Li5Ew4(8A zXStOY_U}#M3aj=G%P!0CINQp} zDcGg2Q3kiPqD(WUfzSay4YmRc&w+FnMijCx^YX$QV{N;I9>Pee@W^#ifBZS)&O9_3 zo<7at^v+Z>l09LYf(i3}9w}yFXIG!jn$isRzj19!%ahR9_=WbBujcWggy1R;=Y#{( zGml}Wgk3F;>HWeFK5FGc;FrQr3ZM%jTYEdVUD-Q6xV1`&%^01el3tB>D;6ZTln*ID zCho0GvC5!g`}ozPHsoPlrs-ndGxIQvuVau;pe2X*bAar_nlG=-*y9!^^-Fa;ho7B_PnPWsN!G=J5_ zqBPMzqQPtcoG4E#CoD)XODC=@WWnrgBC{P@6bqdiF}5aUrhL0-<2Rj8I@!KIwd^e+ z+drK-ICGMJfMbD`PxQ1b;Yo3}+9#oI>~0q-F6s}k6T0LYBR?JfO8w2-csQapv9gRL z<^&LDu^O;=5Zzt=?i-ndV;xrh;Oh_Fb{-^j66FVjAANJh$C?h}Ng3yr=lF=5G*Oe_ z6KqWMrDbz_rR%Y*MF)sde;=SD3`8J~EZGFqFY~!qAfI8{^$3Sw)J_F@SxprQUDubt zCwzPG?DqNR_1a_M0=S2ue7lGtJY_L*g_&$+c?b%E>0TRGv%-Al3B#bae1>A#UZSeO zFOmYXFtL7sm8XQ9zOsLV;?&fR7OWK>T`6-&e~C2BxpThJS4B@#e{!_hV>6syM7{;< zyGA1NJ6~{pI=ZZ{s1A(@tW0VMhb4$X4$mP`w3Iv2x*vLnFR^j*-Z?>YRJKBexHHV= zv|2{Yl@}I^N&QzFzc|p#N~jd}519D0byLo=W$ONGHzjp!GmFWMa3CUwK5^ z^~~T=jUA!8rTon4OtX94)=7GHwga;1SW{lZDqnHki-Yn^2BPfJ8lx1bttThCN}0v(fvZ`&Af& zZ#w=%0Q*q(qaPD=T68@x-AwV4i7+n*u8Tgtc3G^+`e{c@H51CAJ&9Rc&>LY*zis5W zL5+GdoEA?V=$B-04g_YjMoDl${72QA>x;+uU8^VI9F%VENa&Ic^a3g@plVL8|N5uS z>r8v@39Ay?Pg%Hg&UejXY}oX19o3oFSGsqhB0Nc0om5r{$gq}v3)o*KvQ3mbv+oA6 z7Y^5DBn>^rFV=jLPTrtG$TPws6R%6zbhGDYC59x|B<384qwkYw1w-)_sM)1#|1@?Y z&3vy*-2%g;RM*P7jWZAMdR3Lb6y41e*^ ztuYx%8vmnfoAam0Rp#bGVw5&6s`NJM!#>7Z)X5uT!wFH21Sua>r?pMs7X#Lt*5vJ- zlO6V%wf1)McC)e#$Hv}948gsc1pi}%MDKYR@IOWf6|^@>%~bm{|9V=26#CZef@E-c zCqlED9yIimuMiW@4Q>wiL)>007y{|f~%V_Nm^L{BVMuHnZ;xl=HR@3{&x`Yuz82W<4A>noXEFyEO z3-IwZ=JZGwX@Q8;RF0@b0w#xAdz#9e6T#9AA`L*7w@3D-Np-`YqjfP6K}Q}`mv@qy z&zIU2k6Zm@6@RQB<|ImQeB)KyL_-H@2V*B!$Jc$zJ$C$+n{X!nwjG4q$0hoBN%?pb zxweVkUto`U!0&S-h{9Z2RC2P)VHj3gsg$<)_*3;9gMx@>x8m#=y!7=>51#gqk$Fr3TfK)0yEJSu~+|EoR<56x&w zu$9$$SiN2J=t%s@y+nf<)uf@FmE&TQKjck@iD18a2<~qXSNzn;b$Q}exdVn*)_XmV zQo|_Z&ASi)y2b!E7!UM&WaI|rnr$){1LHU zUErE>{ODIH4ixTSuSAkTPB;{LXRA~0lC&#@4DoaleLTP=p)g}$vN860awdv_N3vTT z*PpNyK_A}cN(|yXFGRW_tqeCBVLsc6kB-PNfa_znSIZ9L-!8@df} z8(YBc)WDK+vo&eEjCTxmcjTYG|G6X$S_2vKTd9g9jXbT6vv$PB-u_Oj zYURwIrYEm*4G5x~BV5UfT@z}(vHF*sQuP?aLpZ?4Wr3)(|KvcHu5q7NTG`Ue%LEj%Xkh#jGdO! zhb@k-vK*ftR1W(DRr+hKx-X{dKYRx7pxnA6|7GYgTBKi#-Zr5>tO{ z7)NOtN?}NoU&zA)3aMu8FbdEc^?Cv z-xd;&IR5tqGotzAcuzxK{Uk*pu(zTSIzQ4PROH+>2^p_>UYYt17_nRR0dW7v(!IDd z-N*j}cL?QNaz1sEN;%}rMu)rHI-sQFFqJ}74s)0t94i%3shqc@o60$7wwdD;HgcHb zHiltrV;HvC&-eTL{s*7y`drt0`@CPz*YhD-)+qbzuYf8>2>1cK1YPtR*RBZtYCT<3 z_5{*%{^Scxz-dpGPiO^%M3ON!JGab zP;VdlP<(7$lYEG2Qn2!1auQ`=+fC7Eo|OW=%4F0|4%KUz1&aD>){nPPelE~82q$yT z;{t8ue|$4iB)fNBvIyC$gD)lh_yuQZW8~;H6g)0w1TUSNfQ@GIjz!;`bmqp?6q^t% zmvVoNLU7h#!A|ki;h6DVfw3QsU!NhVLKpNR9k+!sMUYAPVXZ|mb@F3k zUXj_1w&&f14%;%JjjG#C(i5G5xFm=-OMnFQ-hg5i$tQnds^|U#-;9>6PFs*!o5>|L zi%@9RZfO`mYP~kCmTFxOk+mdtN1T-oFDgTHiplRSd2bsP-1!+pSi<@#<7e;3O0U++ z0KZ47O0HGBb@;EKoCwj$L*ZdKt)M0MFV~tAXnnRZN-HbL?s{CV-}piwxv(*|+UU2n z8oEewc!)BP9W}AUSC8P{mmRzDiq#|dod6fzm4`ZiQmvkYtMG0M6McI1Px`2QyTa#D z%Jnm1=Fw~S4*)-_YkdYQw1K#596M!kzyu~=$>9r>P>KLdL7O=4t^lZ-=`u@OV{ zWPg~H&q^JuGqHZ-{T22Ck%8^5UW5KpMQEbqsE{zlNhvGs7Hj%UJw+w(st|v#$ zOdS>-gQs*PHx%nO`q&>6c5anv2eS~iFCt)Uf0eLD#>b}pzKZBwqU);Y}^5z0wT#*@v`-YMspFW@$@16&hdYLHYA zjPPQiCc!JFjUjTz>vx5YsE#x}b+PZNE@@~*Cf}omTMB#jBQae(B%=)*KELe}GYYwY zwwS8)I!)&AP+Ly;7c6km;TRJ|*9rtwSyho;@(s2HBxx}6*}NIy5H6a(ZflMSVixsm zkSNXasW)HkuHYGR(q2qI#>+xWtKx~egg^D4gQtlW<8(l_sHQ2gIL=49+8n1Fmsxv3 zH8RulkYT=ULs^gv!~tS?sPIwhv{ z_8;Az%B-s1aAZeBo=5j3W)LQi^!2>0#O|%$ofcRNs|i0{Az$*TrYtED%e9d*+T4ye zp~Ymhn^{KG3U-F=TXa6MCu1p-$U0T{v5H5dknV>4iTuNBhzc`Xtj!Khz{eD*%OK@y?%XP|Ge8s8H+`p?$?l z1?3+8kd*As!4l6_!)>4sJy5WsqdekNtBM>r)7K!s>8L`#HS_YjkDZHZ`sT0yxN~68 zF2juSwb{(aQR3k$YqiF=YaOIk?O}IY(ldd={qTpWS8-2iHW_VGPM_wB#cop{OfHj` zxmQG<@gIQR3=WHt(LagVIsUow1gXBtI zGouE6*ul_%z)rMU#@w-2>qbpv%?UTENq5H;!u?wf2Hy?6|rYACQ-S8frKB=7a{)AIM3S!Cm z@~N*-ob2XMZ+yG)PaXnpztQxMI9HM~dV{h_#_KRC16P1!sY0$gV?KH) zIQQv;q~&;>x-TqX8u;4PbaL+KU7~psv3YzWqV(`Q<}S%~HG2-AOZ>FN0LNMMb$I-E z8!#VlJN7{%DAdJGiLJ&b&L#MZPgWYT%^)f6zL|4s!w!VhM_VnV&X0Z1m zo2!Z}u;WQU;sB#ZZtQ`}9r#Dr|B8xys$2Yo)i0{Hz)v;JI4?~^g&JY=4P(!_Cx-`n zlLXK=-S;t+Att$F2S#AO2tKh%c#N71%41|#x9!;f_t-75Zf~w{f11LY_YwL7Hz8o= zu^~ZoZVPB{o%Um%mzYhjAYWe>`;NL??+KJ#p4$7B|HoP@%B-Euz60`iw)%Ff+dbG zkmsTXpBDzNVJ1j7FQ?!Ww_DFZUy&*wNEp@69nR%`$3MH+qd9&wt(l3pw%d&b>x@UO z{nXlMh_ehs*5M-&Km`}^-3j{hVAxya)pIn@W|||wEgq!q`xD@Q;Ef(1`^f4iM)zc= z+v3DkbASy#!k|At5qj|(1-Ej33xo;D8}Y4=xE8Bu;P!#;OTJS4zOfh8+=3{Gc=m>c znV_RkgnY{Ah(|P{l~QpFM1J~VyjhHr4*#TY!c^uvCYk7M6W`TIhxF|U(aF|7LuHyj z$?z@lSX2HMYx_!nJ^N|roiJc=0DLYqY2*n$*`^3Z|3Zh2ejQS<(EErAB@_x`9=}R7 zBuFfTVgL2tIv%sIAReDN|KR#)u-rQ-^Y=^D)2tLDZOO?RoX z^PfZVlfX2`>$-UK9V)8In(&RX=-&f&0{L*@$rOd=ak-%Nv?iG21I?HJ`$-+8t3R89 zym4U?cEHo;z#h@XN6FyJTHLj!UNBZir>Ol7$21?@4qgxg%~g^gOGHZ47ZKmnlCkob zw9<3>B(NVnWKTp&ZuvoV)3m7#2K#IV$C_Ljd5Jb?hk>?)AEy?RMr!HWfPa zykSOAU-5pNU8kwvWJX+Qdo-)f(qoA+QTW-NwQ}t=mkWKEQ#)g#`cxp>xkKNBL;%Qr>cIU9~c_f%6!OjN1 zuk$;{H7>Grp`MAeDxnPNWuJZ3Y-?miqAhdp_4xF!6d>f6@21^Ib`qOZP>xybv(#pD z3wP3wcx}FNcFE7!fEQjYI*5*{TKPm9*V`grDAgNiqm2}^xX{!iY@@62!_8%+H<%r? z6sx~%kNiauuvCxSbTl!`Gt9CrQlM$ej%Ej4ftX~hY2__?Ro|2Ei$#)*kQ5?4(ABwP z%e5>XL$z6nr}n$(P#jF2Rkn3E9B7qnNaWF|7^}|)(@369NNhLaOuq!iLCq*RUOSeZ z{T6S_(<;4Rl2Dn1kFeXx*MT<+PXTVeACP8Aa-YQwoND}qbbU_Po0cIRn5S5LJXDrg zL_!3<1TSc7{gU)qv+4ye-U|MT_fL&_Nx0RlI;DAkLLA{=cHLN*YOgdGXLH+gT0yNZ zAPyaYqlmYeF46y^C zPb-UI=z?9TzZEhysb+mrUxSKq;G>Y`doSrG;KtKhUgd06{BKaP@&c89{{JpoW6lRX*mW&9tv>8TYZ8LLi0HHvCWA z(U03Nw?>1)YeWqoRhM0?Nn7Ih<9@g+~)uLq) zqmsUA!V2n|XfCs^VEPI&g1yR(E?iUUn$2?Xq9iMT>&o2tH24V|?)=3G()kw~->0}Z zPWmQ})AKDgfmV~MR7RH^07YIi&&t>`O(jb5jQMEq@}wT$DfF9YEseE?RGL6cexAmY zp2p%$8P*S~Qf1eK5{q@ui%Ln2=jaCsW0@~8t9C%0_095s!7NUeU|X1hxg8guh~3wj zTc$J*JOUyH_e0|&+MvMT?KSeuCHT!)mOCCtb0xncaq^0Crg^(j)KHSx+cB$DjE-$C z;|&Y8d4Cdn!S$0s9q!fEJiGY@hJ3NTCok50YM}bdemEhtwC_t&_5_TdEY|z=m^}HW zDIw@+JE)kcI;V{!A?T9NYDMfPP2?-OsXGe1*OdO!x2tmJX89x? zeh;m0Q{+FZ@$AglS)b<0t~y4gP`X~b&1+i#e%r~(@E;BmjKJ29zr69~ zCtgW$v-G~!m9>R5hPqy^`uz1Q?r5W-mubdocl6D#axz*c=kku#1m;~dwW$5$g`U8v=@1VN+KMXpGN*EOa8Uu1NkM(0s0+)7pI4w%-}t z7shcH__2+b`kHk5ET_n?)^)ULs5vty^ssKpZc_*rXS%OPuQ$rU`*aD%`@NCqan+Vo zjDva0B@VB{B*9C&rNQbtd9h7Pj-}GoVJ4p%t*~YNen1$mReMpKs<1n6W?22-yjf5u zF1p^M5)^za^6i03?~^pLB#^u>FQjw#<1SVvRdf`5+ECxsZmx3bE4~`-t?!RtX?Ncj z5@0p{#%%CqgziYwcSaRcdfZ`JWQ_Pdpowwva&o@dSucj)^6#w2Q`V4Nk5S1-o+3HobT8V zkWbx~gIq6e&Dq3{5Luw<1?fsrl14(rfpYUg0tByjAoM@ZEu(1#ftr+V@qs+gE@g4_ z&XoFFTKOx~Aw!!Hsjo@UtJk+#tnf`1zsTdVqr$O!Th>q2%WGPBk5-5;F=4p{<)p@A zmskD8YD9Fq4Z?JiX{P>xWak;=*aCQYIp{YsujLHjx(_Sb+dGX55WZ{>d15M;rJd(fl(T4`c`cTX$4aAzJ;hHNQ-K~|?ws2G9XO3m( zxu{crr=ex}FL!F{FvDNGO_x0T?#l)Ika%#gQ&9$;b=bjH4aT%z-M$iUd1kFEY^jEo z--w$O(~9z`Iv;2cp7`6ZX|$P2yzZP56Io<2A0wQMm8)TXn~S>YJ@*ZXiOmp;+!x9- zW>(iGK&pLDycaBnKJAVUMB9*}_C0o;L#QO9FYndeGL8wFCfUsuxBIJGImanKW|fmp zCt6np?f(e*)ndJN=FW+HLCkry!lvsfozUEhuey3YN$#XWL++C%iB$C^V6}1Cu>X|C z-zfHCcx*HXL+Sp+eK|qY{+cwO;idXi*$422s4)OuhqlB6j_ybg8i*nEvt6M+ z`YBDzt~f}hDcwE#I!kA;b#CR<8^?f2!?ikwH5PYi3a-cuSkebOMIOuOU6#{Lhst$N zrFO80gR$D2z~6VMno8UGF&W<9ytTLxAFgSe#xV5R*`AsQW?o~meZjLcWrL7Y9^|mt?^+5J$L&048L3) zqQGiF7>W*_OZWOWZ5^Jcx{~m6EXm&eHQOu zLz;CZhm*yrz{(tto6)^+pCCv1uOxF!;mz<)4Q56;$EIk4SgjN6)h>f=FCndqg0WL_ z+f@Xa&^$g8+G?`|zo3-~r;^@PKWdNSC`YR;mFH9|LtDe@t z!@M;T-l5J)Z7HID@EYItk+h2Suy_sL2-LTS`j7CNP~6I|y8e%VST*;= zK1(^Crb#bghtl%CdULCrU-UaRBL6d@+HRw!88qGZVP%iJ`#JDXOmRokIIlkUsEAtJ zN|g-YZahiC#3P%>TK@xQRkPw#wRY^+TS`&;h^!^td-J3)qquwCe}K$nGdg)SMSdCa z>S$Qz8~l_qQm3uS1avknHm&IN{GL4=s3tTo?Ut-9}4K0cl3I3HbZ&nwP10sqZ> zxgWG26LYIll2G&2qgw4H9bivPd5W}G?~p+wwY=?9ZLQN_&P|=b{TD0Kx%yk~<`5Bd z8Ru(uDPtDul|65pg&(FgIjE{^WAZIf^Cw5R1X2DsvcrV$_h?~n^U$^5W`O@96X!lsIxaT!Bse~zHn&;4<*0JAl zcs-EM8TQE+rlwz{0_y*D&_zxiB#W~)fAY4rMxp|!j`H(S7m|}K*|y@9NbXuKr1oNr zlz;Wcbd&CRKZ3S_G`LR?OA3Yd?b#J25e2@X*r=Sq@HQ=LRscpm)+$X8c%1$A9ch$r zRcFeIps%ZwvL;E|_ey$*lUMovsnZ(<6+i2QIV8tKr;~Gz&CO3IIgrifa9@9`hp4?FfY_6`(7y7Xpbv^0EcHBWj1;^Bj(p!%s-;`{TkSUR9SfFUH5U3U z(VW$&fsX)ZDcf}?ZLc*PmtM_HA0=^2{pU0Ayb00RuNMi9iOqW^l!*GUu*F$x2xR}^e_ z&&~mEXSt|UUMb*y9vo>Vg$H!TnaWyO);75D^02gX7_X(B-x!0LWcCO&E$1l5U zW9vFG!*-ebRM_&rxhrkk-|Q2Ydyd9}qIOpAN_a#S-#`TK{B+7AaW0gKd6?lElwb+q zb;CA29iqWkFnfy$*Ez82A_nnfPKJa0<=ePfk6+Pev3vE@GmL$m0%X09=C#QQw4CMy zw$GTRAKv&YtiuikC-?=^vOAZ#TgY2eC-c36Q4MVxy=%AsJOXQ@>3dRr(~XD^00rP^ zA2*Ie-%AMqY+=HvD@)@y8RTP`%77RRzt=0p)bJjNl+A#*rFHW%=r^e?4bc?D#?5yH z)$k2vt}rZ^mWB3t+&UQxC3D#K$`9n01<%t5RwVeF$(4L65oV{2O^2IYwa zgSck+cbWjLOO_w||H6c#l#>wGbE@+}Het_h_aF)E$(@n|17r!aq6QE-0=kv^DKu?h z9U3qt1wg`HQ#MwjR03>S93x1K)83#^H0DTE_u_jZ!YjzQDT96%l%X3kByw~QeCG&8 z>|XAEXHC?s5NNb5`qsj~v*FG^x02@S^SN5jT^nwA~R-k%#av7Y$f-6W#5mUWvjQ|8f$&vUdnh;DiyMi#*F4T(!FF zl5Zf6c|0LADmXb&WkV@$A`pP(XS4Lmd{Nw|iO3jt&JtLL?&JV*ew1ZW)R>>zKoq&t zxtkUPeq8;s8X*chy}iyPU2;6W9cx!ERxmc93$Z+BM(oQWkL$}YLn&5ZrYn4ou=9>x*c6_-zVpOuSlKCNVF4;KEg z{=uM4+8$(T8aIgoO`(SW@uca8U`86PCb`bD{056s9Lvtshj)gA=#PklNo}~cn&Pd& z#>q(>)gWb7j=^f*z0X>>j5SOaH$pQrzI)n5J`!lpYeZ96~(R=V-zdnTyNdRA|BIh&HsP2*R$7e&YzqS`nH@?Z*Sn+q8$7zx> z@}#a?gWjQRsmf|y5;tO=I^I@+>=>hrOCPOywAD!5z}C=SB4h8+WcI%Y1RqR&px5<5Y)B0BK}~mmfdHQR}NfDV9#9h zo<#;9&L!6vZS9Ppin%k6-to=jF@|Xm-}9p1XFFOs1X7&ef)hYxp>J`J;}#@9s-?oJ zzBX$Ovmmc)Gk+2nD-op1buemy-2?9Vb#1@+zth`x7oz|tNOe{uyD2$P3qw?n-_lqp zsOz~Z*nx~w(7dn|& zAb~`N8cK#117+H_Qg>pwkd+rJtM59;q9dY#8O?R6S#@p>$a&6oN5K=8@e4d519CG5MLo=PzZo?R%4(^}Bi(G7 zit+WW_bL-2Paz_+9{m2b#MyoFH3>$UQBZH z5;6MoY1Gjif-eSNB@tLD%F>^WmWV!vZI)x3XLa96k67aGBOU;I*ZM2ka(^Xyz5!2a zVP|vINzBbB?d73bP3IiuN2*DocjX(w2M~pGkQk8CVvVnYzs%;$d+6Z$RXMCxGir#& z*@lCFTl=W%w{O1WM5urSBcsC^*{a{3z9&3PHdtmF!^D{G|# zv6E!^=Mo1wm`NyOI{UcP-#mUvDTeE^Ur3!r1cKKg2f+uA&b-`Mm7@ z&LwXN5GU5Wx8Q&@|#CJR;*nr9&)DK)3HX*}@rzzpYT?vaY0YUS-IgqpvH>4Q)*H-qzp9`xY5ulP!bwGz^R2o|VvTki%O3clWZ z5mV<{P*=sb;xy7?P#IdqS8Os0MJDuU67MGZU9G2jqjzKrZ$Az zf7h}f^MCS`9E|%)NOZKtmb@( zH7+OIADA?fGQQs1ZT54Yzm?t9!{oQLfLpL3|L+8v>~M$<57;TcsSk5L&0zw#C;G=W z5oLygYxCx~Ejh@kGJz)ll{JZTx34qmWmSEG)>GWT3F_>B(Z75x#5V~#0Ejb?JtOa1X% z1>~^n%}|jbdDE-j3MAVw(78XXemW2<>8&%&5Kfs)R0f{eQF_&zvO7Nc+4pTtJAa48v$`?9aa1- z6!6n)xImiCLDBMy<@Zm)yEAqV*m`NFj%m9&gb!62PURcm;C!+_IaY3ZU#{-0SV#)U zCq1iZ`);ITEbXcD`aL%b-`P#e6>ORIHVN0eebFf*nIzfMvpNxl+OnAwNBZ!_E9>d} z4V*eFTQ6%A9UB$39tA=^od|x~P?*|#vVSoea3_9aZrsKUQe(gI&ub(5dHS9$8VC<* z?(;p#5lj>fG7MNs^}{KoYyv}L;SL@1UUOK3edsl|1V86#ZUw09*w>Ty)7N8Zfvt+i87p8J=(O)FlVn5Afoz9yU3Tcn!E9u*je`d7qKmF(m91(o=Qb{+(0ij5VQ( z>uw!`mE9ba+8%2qPQJR%G_fTI>*oDvn!DqY(M#N0UMF#N3amgRX)b!>-aXqDFO+Jw zt`)A)CCyxb!ua+0DkNhnKWa{+vQi7za87RP7gyDru3ug`;~@*2@LXnDTNK92$av7i zp(|y*lqsV5m$x*H>7A!;GfPro_0m2U=i{HCqr50$J>w#Ueb%wHMgmwQdQus*DK0oY z^!##Wn{N`Av!r*Tq{I>$FKo%D{Bl@Pw#5o@I&i=R6?*W7+lw20pZwGAPnrD!{!<|xL* z$IG)BVqD$&pM3@1%rmU=sDNXE_Bhhv=de|D6iuV$Y;C~0t@B_|ciiPV{OpQWc)4Ui ze+hZkAbeg9%i5CkT46VMV_#09;Z5{IQkpeL1S6YM`&iLs=%sxHbgqCdmhAFYCk`)n4o zVkaigm(h%6#dmu|pc~h>B{p9uoAQoa_xAjJ;zKJr>IGh4FJ!n4HXC`=k-NyE=kcw)!q^NoR|oqkSW^+iiwX^+gB74ZanHkGK}6YUML z4-a+vPP`EgdKd!45GJVXS5v_z-KWNR{(O)Sn=zlFXDv5n?GHi3Z6JGn0x$Um+(gJ zt_UW-CW@rtqf3YBOE~mloJ{~xC4}^^_$Odav@ZVuf<}j79MUX1ZRo<8l^gW>(I}oN zE!T+)dfYmd#vvwT#iNLir%T?~Nvz4lYg(6kI(on0$22>0>y@wyiCb6(I+y#YJw1<= z+uV#mcn2%B5ir;d`mvR^EigfFI!ofn#CYo6mzJ=aQ>Z+)1>IlVDGsTqQ?McE(tAc= zk*8F_Rq_(Zvn_XN`*p_=sQMS6xaFYE(N)YfijZxeRd!}-U}hb~J!}vbUzH1{r0JqX zM0}IBzN!`H)lD}f;0qA&+3vi`vW87xqk~hAj8%!8!iw8}cVCL1k4w}t=CfGr>XfjO z2k|!DHf7zTrw+6CeYeQv{`0!-aDe?e`X!Ju2v$mycWFC+W`Fn8sbT6)S>V)G{)t zu6ko9kFLBNw0j-8^_T&6ftnvoQUi4eIp)JXK{wix?B8PKVglQ^=bvg&4-ah`c$2=x z$NB-Tq}^9EDAD1lc^4!#2nbNn09%X6BCL1CJWGtad#-7Jz3Q2l2L~~^-wqyN z{QY1}Ml}ah{4LV*aMnr+4zW(>OXW12J2Q4CaWV1}iG}w=Fztm-ujj6h{V)phFj19VT*ZN8Co7q@8b8(1NmN$e@84dO?ADjL zyX8?|dg(U89GynyNRk;m467TXMf6o2`Rp%qcMqG*oWwE z6i-mj909zOqC7bCyHPw$8fSN2i2y;-^|h-2hsyl?FEv;`nJ!z|LG*eF2C%=e#MKaj zo@6=kC!kxxb1nSK+c$%ypkk|+Im)@H#x;G6fx>UXuPqyb5Ry@+1ATq zd^yu+RZK^I%S?iqd(4k9c7j*~^&8-a-UhYzix@)hojI^o36}B%guH|e()yGAisB3B zp9nCP3oM=Faip*Ly3Bvr^_X#f)~n%AguK#boA~fIt5U|HIq>*9R;%4^_BFwx@`7zh z)tpgQmi!jXWgPBZjIehflS=(hWitb;`~8@d&`T(vr!#LWzLmQ6!8Y&{4;o5IR||R6 zB`V=OLTW^YCfcl7-A~J(0EIm9i|6#hju&yl&j$v`yBH{ZqL;<4ozo+ zsND1K9_E-4y|bJ?@g-VpS&bk3JfF!GKO--($n^p(xEJtFeCqiU2V$^u+cu}h#ORn~ z5scJz*pp)R3n{)^z5UKk%!UCR7(DFjO^TRQ5-od8|HH7l;Zd|m53iA$um1slmi(YQ z(>6M7=91n1IN%2^8iinu!=4Qq>#J4##d$y8Ja?#;Cje3PC9Ec^ObW>~#o?cE?-Zsxu_S)ac`6IUzRVQ(zAXvriGhIjD`*m+D4{aHudUf| zbsabv?2~*yUpFqo-4FiMM>rQ(FcN7>w{Tav!Ry=L1&3T z;^V4WUr)8DRwdAv1ui$cZuN;mkY${+ty6=pbE{V=`@;;ve}^EAR-CR#W}Jvcyznmz z8$joTI2VU1en4>MV{w1W8!Ekvaoy}NnqV+8H!se-IW95n<)l>Ga>_q zSpzQmn`OJ}#6El5{o|n`Y07N09AiDmV?&G8y~5F%lL+`yzF=+j`R*;c$mzJyB*f0K z+{elqZro6KQfya9^SOzl&D&DWPYSqfxE=T2!8UO7K*r6l@u`)kQ@n4sm9`v}VA3W6 z-E}_?G~ub(NEMcVV|9!DLEDn}IH%qyWTS)=t<&}g9k~d}_WcJG%Qdwb^r3n5Wi>X@ z6t45-iZkk83b67zC27)mB~5k(h~8_jx%8;O)jTNLQ`Bqk}~(McQ(g*NnY-AQ&q(pvsjt2HDypJ85ELOP%5CqefNFXa_&dvM&*GUB>e(NNO6 z!mr%Tc4IO7@hae>vbS}_EZ{_OLR82Ooo6o53e6L4WRvNqS^0@v1$fH2JcqCh#C0D$ z6d>8lP=GL}Ym9LTkFHx4deA0czDFjGNYD6=mv6q95LE`Yb9QBA;?q)lMVbc~45U89sRmTet9bb*oIjBJ^_*e0 zmSuU7BY7b-4Ru}_@#6;a-`A2XU}P1msheJn_p9`8uqXyg12V`YJ>88#X0X0C(w zi6BLhi5bzkaDgQo42`b4S-gg@RNRFkzGH*;&_xFCx!ATa${A22U2ORq-829>LZRp? zB}+_ptIcK=$bJNBr3>l2X9b`UH-O;CWZ-~+y=m?u%wsHEg8H@DOV7)zsh<3HXTD}U zLc2+U@z5Lm$~RfsXD#U3v&lsD>KSohd}}hZ>rRX2vA&}Ra9!5&plM&&wHtrMp)s*| zpe?*0|F&D7&¬-R3wNcIf5a2kJUes%uH{AlH8{w$sL{CEtKy-u{m%7juMM0Dc&+ zvl$w1x8GwxS#a9{?Wu!KQF8=LKy)ck~Z96J7LsONu%!K@Yj@FwyX87v;R! z#*<4T(&i1HDzVo#b;?Wsk>O*L1lk^sF1pg~!85-PLXqHEjDEe`Kohw+FwAAJPoe#3 zn|bPs+k^Ob>9wFV3BFaI4-sguE~`%|t|c5z)C#ZnGkwMuP>A#A3>lnA@9z7X7Ly#G zjw$}WPRq15Xh~fCc?+ktZQFaMbisoiAy1>n#Yka^cF?p0_I6^ZUUPdPDcWf)>8aKS zj^$=Ev+qi5>Qm?P4QDe;G`IMi{@%@g6P*%PaM@^$uB|I8iO~W(^PARppt+?P9IBhX z^N2hjk#Zc93uq=ZsHif|xH!DXteuaQ3Vii}Mi5rxh%2A%2i&^*dA+`MtfTV&YCR74 z_ueEU?>nJ#4@typ9cu&!j#|OKw06Nn5WbvoRqEN~Hga?%X$2K~7pJG)+5MnH8nnBj z=<)UFs#=;fv)9BjOLSo9TcapqD3Cm)_ zQq;XysirFIVTGWhU(UDE&q)YbsZGs3s_60z4Bjz-6{6?FEz2IT|d0AGzhV0t*^3(@41fs41Wn_N^d@B z8@uJDHK)+|S}z9k<-AGSaxr_hyFSdjPHB4Wp4K$DFGw$c>_0k{QBVJ$?I_1xQu%+x zMqt#F!lNGz8{zsD`#(U7ce`pYc?YA?tPBs0b#vS$G9RXml38GRDU>#9)GD�&1U` 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綢ra#>)B-|4K<=5O0Qw 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

$9g?sUySq6s6GQ z&0i-)k0mGU*_JRZN%@&;wPOOBH$#`BTYoJaqe{Xfr~y5Kzr?{vknecy4G>ERE!{sA z?SaXiQ{-3DMj*X6UNA2#d&mqW-SI7qbqR833~W;uEEIo**=B_I-@A(bbVfz?9)rJS>4S?+rYF~0>r#e>rU0p>v2%&7wXCTe2(ha zO>buN?!yz0oY7VGdi1>!xcNQ79l^Qiih~n;gVyFE8l>0S?$_zraSbfuq;0pVR&W)i zb*sD!U_!6o0`{6%5xr+F+HkRwH`)zNYEDp*{Wcyh(N@V0p~{UQ_R}?1o&H|+0*>qm z2IcuuUJOzlDEZ@!lal{LMZdp;NE8EV3rTH)lyf2bujt-*dD8O5ha;?DrI| zNWD|bwxR{~n+xb`&s&Z+E?g)GW}z);$wx^jwuSl4HlvV5*NV9T=i*l_ZHsP-8hu4GbX;1L!?V>* zR-LtW*PkiX3nxq%7<+f_6kAttY(Pg0KlNcDyoKe4`0Te^J@0+X(I-;YTdPN}sq2cu z`d)v6Lu$6h>eN(kAph zUx#(*(OoT)0A?bp2z|=nokJ25tDBU{-ytBUbD=ICICiSQH{_eE6<$pKO6M1jXYHKj zn|bI@?kd}2&iN6t3%}NJJvVvSrnui&h=Xy>X}U+@>(~~b@N54%$JhU2?E%*xBq*IN z`ux>`Y_*KQGM_b1mWOPB(h%pVRc(MT*;hfMm(MY0VA=@Us4D5lYjGSQ!#chSoDe!O z0jK^2nUAZj4?En9zdZjZ+63KPvjOSyuju%l$)%o&b!`Fd>(#Ug>*CkVgzISQamh6D zCYqQNpo=Y|a1N~o%R9O{ZD^1ZALU^5t9`to&mqHk*U{wm9MSbbiSB<1x!3m=4{j7* zN1wS9@{4A~WjUDa%{O##s-HxeDt7(HRkQ1yvGh&;rPE{UWU>tUz@_%$5Q+0rsXy6~ zR0(h|WJT|VJ#QOM73~8Uo7;uYTBSz*5ZFj%P#!Km5&#+3K(}=<@FuMQ{;q|_l!Phv z3);V=3K%nnol)m`C5`KnTiEDCPqe?Zt7-H2^-$Rr_-&PAw|Xu25q5Ip{J7dP!iz*| zG%%fLO~(rz!kHhHCv^rLZnzz)c5e3D*IcIgD`| zP5TvK_XaHrc2=bzR7a4pql=UM3H2?|{8DR5{h<4Sd^UpC38EGLO{bwoD2}UCKZlvz zewh>}0f*)pv5#8QVw}p}feYAM$#ObkC$z$kYX+DktW%48>vxsSe}dv%w(^_QY$uv= z+1=dY))0?6JL*ff>sk%y8jRGZ$Nyl4@y3Y;V(MebW~skTW`Bfnsz07mIa?1Y6n&%9 zj{Y!Kwo}i)>%uLp$J*e0*>)j6$KOg$w}aNr%6o#`v+`}xh*v~u}WLi z1`@hBuZ+NS*nq@<-uoLb&G)*pO&(HbOCxA3pMS^1cO{32lZ(iTZ@STnS@rViysFpf zQmJ!~BY|dsXJSP$ohMrnhPyLA(5QM=&$1JuESO-AMKsqK8$AB71+bZPj_IThGyn&3 zLRZhWzeQt2kBz9*>kA@;q6;=<(7pHOO^eBAm4w^*LRReozSz~{$10Y<52)FJcpete zr=2ot|DsX6(?J34DZc~RUokX|x>8sxn|65rBe*;_1{hI?pR#u*da=dIgwv}9yXYyPK=taQ&C=L^J z_^x2_FGkMeMGx%A0&xEEPJYqg5SXCE!*IxxB3V-$x_d$~2>N`gXxO6$>7&miy9; z9NT9cg7#D}xBpU$v22!fGw8C-;cL5~`ii0O?^h4y>oz-j7NwC>#~nl<9^e75NHRK% zxaGrDBPfhb3cimJ)gZ6RHrMS;xBPXG7axJiJ%ZEb8GWw(2YFZ^BhW7BRQXI$lI{8u znax(*Gz7@b?p9bNzw>9JY0`q;sT8 ztm)!k!rs9FZR@`K;n*H+j%A6g5^Qo5w{I1aNC*Obl0g=B&kV|plIZK>&b^a)0YAuM zfwYC*jp8EHD6v&D%6(Y_-3bz{1yR~(VkZhZ5`C_i_e*vjTH2CcI}1!xmla}dgW84= zPYs(_Y&~Ms((e2=)xk4ME^Ua|GX8cyxt3tcei02nC<~9ZtpC!w)_Wmp;@E~g+%tWV z{=zoQML8p|5u9qYugfU{QUKeyi|xGG;O|;t+LqM89P|*p! z(1hXi${_a83knNFb|d?rcpQr8ejOq3Zrknp>S3CiSaa2Kz?)2|QF?H9^dy>?ro^$# z^=!2C{vA6~|LC;0Uis5?xbz*NStgttCXGCKKxXjUO+E|>4`e1f6n2jw!n9~>02l=U*F#7ed^1p8+i0y1{JlG<1kTlt- zYuC{Q_`r+ylUHoGtb~7e)`*AmZJU#9%a#+Hc1UaL^*vnfgEL+jGrGM^b$Rc8htXjH z3MZHB7wlWq`LJ&v)q%Mkb|;XThKl{gy`_Fl=Pc3OU*uUS^1NR=O7 z`m0oMwVn3`yGw*T(D(G;3PB!VoW*9&IQ%ZV$KRMN*?=SHcbBI6#4&{pWk>SM1~6UHOH1)t4^RpB^MU{44kC40xZ8s9#tI4)I! zQ-#~8!i&q@8)oNn8a(fX11#FJyi=R9f^W6=e#g!PVizrzc$83}urx-Yn~$!vhy z@){;yUE*r6*h8fe7V`HeaYN9l`{ui7;XhRq;`%N`bxV`$0tKICbIas<)K;?x3wE9i z)3LZs+bX|BzqXqDA%bcIOGRVH2d4A=7FZXPI-QX=YFq~F8QO? zncV$#%)kIFq>E0I+Z(PGNRgEk-;q5a9BcN8=(dIbbXSa{Q|MEZD{y;kN3Pb`p#iy? z)!AsEIe@nxu*0~@*g#}@y+SR-O+36tt5>FMFB>ATf)9*u&&)zX>2VtBL1&Ec0W92J z9ly=iLP!zUOa$A(HZ)(p_SCa;F_z`MKjdm0CZN(%m8beMN5ZfdYu@nuj}Q{p4zhcK z^un+&gkOCU6}X5qT%9dRGvuAfm~$dHUbd^mzs>e4uq>o+1xVv!f-))=t}sV?2~HDP zROv+xb_Zxr8+nawmb)+05A_y5%-g(FE#5pzDN(1|EL~Oh-}~!$lz8yLLcNcZKrkmH zuGQv7hRtK(+BHf!jPl_A`IGbeP)yi@s&Q*XHuPwM(Xw~(f`%|G&KOCCjwgvw*ShHk z?Oq=$Y?H)ybwUY6ZpTh`p|S(>fQ>Eoyc^6Ik9c&<+)@4QAtleVu7?``8f3RH< zsolSEW@@cNbDLRI7{{jnUzV-(d&`hc-;CYynf$0??RojqPHiAt0Br}2RH!IYE1rJf zor#yEvIHBcFt(P-SEv3AINFf*N8tPX^K!FH_i@3N*%Y0#7J}fuQ?shu@ll zTWx?|&8X|0ScIuPjyZvf%JvzvzHE4eoF10nM7RK$hirJxwNL9pUDX|>3T;==@E8X98582yvRzH|0HX6*n(|au+n= z062949HJox+>rJCC*5LpRVOum^wi#eh#5><^#!-xwSbW(YkAg8iwo zJ5&0A$JSV@VRk|>YueMQYMmN0hjbCjun7OlmrJB5gf^>6=AE{HT*b1Vq9)bi3P%N$ z=!;1Oy`ZYg-0xO>k33ohtHtb>>;(vuCVe3L-{@@gDCz$jonf|%2Tq);cZ+S^vD=q4 zpd@6h3%gR0)X=j02Dbe}otmpv$-2VjZxe*J$LM;Cq;uvOjhL{y)Iv|x0|m2Fh&;0I z)UmT5{lAjj8>Lt=!;Lr8T#w+!+x*^8SbH>=BK!bc!|O+n^IPim9$sC}pQ>9>x}Z59 zS9iP^zux9&dO{(Ky3ZzNH18XG!xot)B{S+y?s}~chddrhx|GSgM?>EC&7};PhAUk9 zV{XPw`Kk-ah$EPF7tFCYeh6uQOr?iErdkt+w&mu$D0iX;`;UZI3h>jvjCl}62qB$;p|_G z`qQs-XWWv|QL(gK#_=V|Hj)m-JsY+yRNmifY1eX{8j`Sn!7QhcfDiM>!1?%2QX)pM z9FbKT6#95f5o=T-IQr0T9sQ=~zy8|4S=tn>+9Za2y|I&^K!)7;(yh)rV~qJ#qAVOucCYfLaz)bnim?;iek2%YdJO*WciTu_ z{M=^qag1_P+hPc%w2u7GDq#ACE~$_WX*`)XS%2+i{-i8T@38LdF5;7s1N`&9(T3>k z>Ls&@#?9jc=;Qyzd6Jt@)ErB8unKb#Z*#Ck#Uju>OKn5=e3Iwfnw~xO$4myKareHl z;9=^EG0OPk_%=&qg_Ps43b`JjoWIa4nMcpP^5yZV1RhQtY_7f<>HKm3k^SQ~JUg$F z`43ggGH@s_!>99?Qs^*?(G0Ip6^#@*sWh}IgKKFhy+6rHK}Y+zJdyo^b_hM?$Y}h6 z>&--ISqme{j%_e-F@$F$_s5x*@^@qpg)=(Ona~AaWnjF>CPl_uMg&X-!jG0UeZ-|P z{{6xb4R`a6Rm3&4u&+tU0v|&g#A#)PQBcn_DV(JJ`yD0BM)K#hRry}|ymEta%o)|d z&vZz9r*m9}FpE-YM<1hig(Qs<`yzJi_9xIW01dxz^99X6_5RnCTV*Q9Ro6ND*1Dr~ z?|1nn&T|$&CcyMhU502<=Tj7$kr9{}xMECw|A$xd6~1aV#Afs6u+R!q zu(-vh)bUcsZ83XTJ^tyhxpA3V$kr!**%^R7wV3j6XowEZR*j1CEmLnIS~A^J0Jm$M zu0@iyM9Fa`6Y&U)WX~M$rb+G`y~<$uxG_Gbp?(5;8to3~${B`{@vEe_)waZIk@E36 zOLiVdeaX+3i@7(cnibLPbkyRliy?R?-miM2N8CjR9&b=NUjcDx;+(Fa8CPvgPte(a z(nW*H0izcVhnw{BUSB&sLhk%o1rDu57|{-OQJ!~)w#In+ZB_h}p$eY}9=3hUhhBAPyzSoM z$0JNZ-HZ2Je{TH=u5KM7(R72mOY>P%HdT6`@sWJ!8c;M#JhL{nyy*yb;(Br%#&()( z(Y-bfG{rwCmDv$f>s0rr$z-zVmpjI-fAhg`hF3Jik4MCejt_B!L`wR%`~5XPwI{P= z1ixdXxKBjd&z6Arl3;6a+E{yJcN{woURD2>=(+FC%4uFN11j(b(M*L6{i0v1{zr8b zi}`Mp?Cs)6V-e5{__W01!cEuJglW;QI*)_b=?~!u+D;>yGU*=(MXxul9itfAcjU#{RhU+0kGYfI7RuarFjToX z8aw3Yh$>ie-1S~x>9Qn+u3|1fNvT^=T95^LJ{N0-4L;@<$96-VQFi~Oop;y!wSgbj zg(}_6AWQKp;Ft7Q8xlUQUr32OtIT}6R)JYPl`w5OP5vG$9=?oI=8o8$I$>WyKW393 z+=fd-JCEXq6L8 z{H&U|vs5y6I)1J>&#m1OAJ>&RDoTO*Qcx35LiR)#ggD0D{ZGcTr3Bwej5TidyVLYn zt4JuohCymqB@o}JhMNqSN|i6x({9H6;rFO)&*FvX(9e$@bdk^0xc{O2S)hU=P^Pr1 zBBPesPyKZ`KYFEntp1(x%7ik}qDPrRI;*H_%(+#2W5>q-xwDsZg_quz9WNLvi$74X z!D@-;8wcbLT|)ZUa-EYrzq5ueraYjUuwOg7wj&+0*B;OTWPcGwxo4cW>N*OgOTG+iP{Ab0 z7RI@Z<9j-#t45lWJD7RVt36danPk|aH#kfP9!M1u3^ zGuKshW^EBo`>wje7iJ~5c@L1IXIIvCbr5>}iOh5^Xl~nV%Z9%flV=B7)^`X1syBg+_^{k~+6wl9H^su*T#gcl(eQxm6O!qVIjO%-cv)9BVn` z-U-6z3vCEH(Gp;e!$T`Hmu+5-8!9t;lZcUa1gbXEsZ86-%%&=4JXA+bj?{8otqZ5_ z9KYHrK1+4t8|=-pUxp;HPi>id8Pbr#X+wu@XT{dV{)uN4vE&`cE*d*7`0}^7--e=+ z_itIctRDmy7e1f0a$N2dTKO&>?y7_ zSOq?-D~fxdGx%0FcJs<_-8#h?u2a8p_I1^5WM2lX`;HQu5l(Yak4o?*sqAK`9y3)A zxorGVDU5z2AbZ}MV7$)MyU$i7EO{$fJt9UqI`w7&1ml_F@FG!jJvn2*3Xys8N$zq# z&R-*zA2MpeOW9yjl&DozF~WC{HsI*BjV&jQ{#vn4IDGAt9n1b%+AxGMz+?}Si6Qsu zOiF34))CEuMZK_7E%n#q?J0VM={Ue; zNv#oOo57dUMc?`NO9+iVH`9zhf0B-^J9A2Sdu9JJ&D8liHnxOuV|)5A$oY3Lt0>bn#SsJOVOP%WhI-* zf7nqy_6dYRn~j~(DDtJ(sH`fHdQ(TZN9_VDvI@$PbuWXHmY=h0qVG)f-;ZFVnI3!i zdi0Ys#xAktD)HabW9|-*ld4!%g$I~SX-}g0q#R56Wg7ndq(yOT=-Ao`tm==~l?0w4 zz3E#0UCiE=Z>$y$dS>f2@JQez7^-A9gJAv`&Vm(3vF{j*ztYaU#lG8}&{bcp0&1;( z;IW_?izoF;=V8LfXah#I!Pv*bs>W<-sW*`D{)FLz6(GFGb-CUvG*~EbbVRfDR!J}R zUrQ=Xsawzi~dKMimjuuC|ob$G4I9$$8S*A+y=IoOsW34@7meOT}UNGroJY ze!xK7E$|01o9SErmOJBjGIotK?|`wQuu=Bs{EDuT{1@3f)20uXh}lFG?H7nCY+{Ac z8gPnm%KWE~y;FceE#RL49}(8BTM#o(Q3_!HBic$mHekEOX}p8A8!SS=fguS<$T}(YQGitBHgg3J&4{uMA5lrGh(>1ftRXsq))CFHE_bIx5!u2egdCg``J!N z9N}=kaQU810f}MH%Q-~?ok3rrtk0VHYgZg4{XeyAj${`AuW)oY8|n`!$0{Y;JBPA!j8Q%?mP2z>OAt zrxlq=#@0ek*g(JaqxhK>;$H*NaJ9>LPoZe}G;ze<=qV>)7|$#WCi*O%xt9&cFOl_S!gXkuVtFTG|vjE=sCxV}o@^UGrJZD}Nl#s{f{m|A4wB^0R~

-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

hK*)&w+R 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 T000310RUqF0001f5&!@I>Qm|r literal 0 HcmV?d00001 From 80647d8f14eccdb523b5cf640d5479b0db1aaea6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 14:16:03 +0300 Subject: [PATCH 0289/1064] Added/Updated tests\bugs\gh_6915_hu_hu_test.py: Checked on 6.0.0.553, 5.0.2.1580. FB 4.x not passed - see notes. Min_version was set to '5.0'. --- tests/bugs/gh_6915_hu_hu_test.py | 310 +++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 tests/bugs/gh_6915_hu_hu_test.py diff --git a/tests/bugs/gh_6915_hu_hu_test.py b/tests/bugs/gh_6915_hu_hu_test.py new file mode 100644 index 00000000..3f975171 --- /dev/null +++ b/tests/bugs/gh_6915_hu_hu_test.py @@ -0,0 +1,310 @@ +#coding:utf-8 + +""" +ID: issue-6915-hu-hu +ISSUE: https://github.com/FirebirdSQL/firebird/issues/6915 +TITLE: Performance effect of applying 'DISABLE-COMPRESSIONS=1' in UNICODE collation for LOCALE=hu_HU +DESCRIPTION: + Test verifies only PERFORMANCE issues referred to in the ticket #6915. Correctness of ORDER BY is not checked. + A pre-build database is used for check, see: files/gh_6915_hu_hu.zip (it was created in FB 4.x with date 31-jul-2021). + Hungarian alphabet uses several digraphs and one trigraph: cs,dz,dzs,gy,ly,ny,sz,ty,zs. + Test table has uniform distribution for following characters: c,d,g,l,n,s,t,z,cs,dz,dzs,gy,ly,ny,sz,ty,zs + (they all have been randomly selected in the loop of ~ 1E6 iterations). + SQL script that was used to fulfill test DB see in the end of this file. + + We decompress .fbk, restore from it and check that for every testing queries number of indexed reads will not + exceed threshold, see 'MAX_IDX_READS_THRESHOLD' (con.info.get_table_access_stats() is used for that). + After improvement this threshold could be set to 1. + Only columns with attribute 'DISABLE-COMPRESSIONS=1' are checked. +NOTES: + [24.12.2024] pzotov + + It seems that commit in 4.x (2af9ded1a696a43f5b0bea39a88610287e3ab06c; 04-aug-2021 17:58) had no effect: + performance in 4.x remains poort for queries from this test up to recent snapshots (dec-2024). + + Commit in 5.x (cfc09f75a3dea099f54c09808e39fe778457f441; 04-aug-2021 20:25; 5.0.0.129) really SOLVED problem: + adding attribute 'DISABLE-COMPRESSIONS=1' causes reducing indexed reads to 0 or 1 for all queries. + + There was commit in 5.x: 171cb7eebc365e301a7384eff96c0e3e069c95cc (date: 17-mar-2022 22:38) - which had + further improvement for 'DISABLE-COMPRESSIONS=0' (i.e. when compression is Enabled). Snapshots of FB 5.x + before that commit (i.e. up to 5.0.0.425) had poor performance for 'DISABLE-COMPRESSIONS=0', and after + this commit (since 5.0.0.426) performance became equal to 'DISABLE-COMPRESSIONS=1'. + Because of that, this test verifies performance of only ONE case: 'DISABLE-COMPRESSIONS=1', by comparing + of indexed reads for each query with threshold, see MAX_IDX_READS_THRESHOLD. + Before improvement related to 'DISABLE-COMPRESSIONS=1', indexed reads were huge for almost all check queries. + This is outcome for 5.0.0.126 (31.07.2021): + where f_ci_compr_disabled >= 'cs' order by f_ci_compr_disabled rows 1 ==> idx_reads=122087 + where f_ci_compr_disabled >= 'd' order by f_ci_compr_disabled rows 1 ==> idx_reads=182562 + where f_ci_compr_disabled >= 'dz' order by f_ci_compr_disabled rows 1 ==> idx_reads=243178 + where f_ci_compr_disabled >= 'dzs' order by f_ci_compr_disabled rows 1 ==> idx_reads=60339 + ... + (and similarpoor results for 'starting with', 'like' and 'similar to') + + Confirmed poor performance on 5.0.0.126 (31.07.2021): all check queries have huge indexed reads, + regardless on 'DISABLE-COMPRESSIONS=1' attribute (i.e. it had no effect on performance), + execution time was 5...15 seconds for each query. + Checked on 5.0.0.129 (05.08.2021 04:25) -- all OK, indexed reads for all queries are 0 or 1. + Checked on 6.0.0.553, 5.0.2.1580. +""" + +from pathlib import Path +import zipfile +import locale +import pytest +from firebird.qa import * +from firebird.driver import connect + +db = db_factory(charset = 'utf8') +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +tmp_fbk = temp_file('gh_6915_hu_hu.tmp.fbk') +tmp_fdb = temp_file('gh_6915_hu_hu.tmp.fdb') + +MAX_IDX_READS_THRESHOLD = 1 +EXPECTED_MSG = f'Expected. All queries have indexed reads no more than {MAX_IDX_READS_THRESHOLD=}' + +test_sql = """ + with + d as ( + select '0' as disabled_compression from rdb$database + -- union all + -- select '1' as disabled_compression from rdb$database + ) + , + c as ( + select 'ci' as case_attribute from rdb$database union all + select 'cs' from rdb$database + ) + ,o as ( + select '>=' as search_op from rdb$database union all + select 'starting with' from rdb$database union all + select 'like' from rdb$database union all + select 'similar to' from rdb$database + ) + ,e as ( + -- c,d,g,l,n,s,t,z,cs,dz,dzs,gy,ly,ny,sz,ty,zs + select p.item as letter + from list_to_rows('c,d,g,l,n,s,t,z,cs,dz,dzs,gy,ly,ny,sz,ty,zs') p + ) + ,f as ( + select + d.*, c.*, o.*, e.* + ,'select 1 from test where f_' || c.case_attribute || '_compr_' || iif(d.disabled_compression = '0', 'disabled', 'enabled') + || ' ' || trim(o.search_op) || ' ' + || '''' + || e.letter + || trim( iif( upper(trim(o.search_op)) in ('>=', upper('starting with')), '', '%') ) + || '''' + || ' order by f_' || c.case_attribute || '_compr_' || iif(d.disabled_compression = '0', 'disabled', 'enabled') + || ' rows 1' + as query_txt + from d + cross join c + cross join o + cross join e + ) + select + --case_attribute + --,search_op + --,letter + max(iif(disabled_compression = 0, query_txt, null)) as q_compr_disabled + --max(iif(disabled_compression = 1, query_txt, null)) as q_compr_enabled + from f + group by + case_attribute + ,search_op + ,letter + ; +""" + +@pytest.mark.version('>=5.0.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_6915_hu_hu.zip', at = 'gh_6915_hu_hu.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + act.gbak(switches = ['-rep', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) + assert '' == act.stdout + act.reset() + reads_map = {} + with connect(str(tmp_fdb), user = act.db.user, password = act.db.password, charset = 'utf8') as con: + cur = con.cursor() + cur2 = con.cursor() + + cur.execute("select 1 from rdb$database r left join rdb$procedures p on p.rdb$procedure_name = upper('LIST_TO_ROWS')") + required_sp_exists = cur.fetchone()[0] + assert required_sp_exists == 1, 'Missed required procedure. Check restored database.' + + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = upper('test')") + src_relation_id = cur.fetchone()[0] + + cur.execute(test_sql) + for r in cur: + idx_reads = -1 + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads = - (x_table.indexed if x_table.indexed else 0) + + cur2.execute(r[0]) + cur2.fetchall() + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads += (x_table.indexed if x_table.indexed else 0) + + reads_map[ r[0] ] = idx_reads + + + if max(reads_map.values()) <= MAX_IDX_READS_THRESHOLD: + print(EXPECTED_MSG) + else: + print(f'UNEXPECTED: at least one query has values of indexed reads greater than {MAX_IDX_READS_THRESHOLD=}') + for check_qry, idx_reads in reads_map.items(): + if idx_reads > MAX_IDX_READS_THRESHOLD: + print(f'{check_qry=}, {idx_reads=}') + + act.expected_stdout = f""" + {EXPECTED_MSG} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + +# End of test. + +################################ +# SQL with initial DDL and data: +################################ + +# set names utf8; +# -- https://github.com/FirebirdSQL/firebird/issues/6915#issue-958497709 +# -- contractions in Hungarian lang: cs, dz, dzs, gy, ly, ny, sz, ty, zs +# create database 'localhost:r:\temp\tmp4test.fdb' default character set utf8; +# create collation u_ci_compr_disabled +# for utf8 +# from unicode +# case insensitive +# 'LOCALE=hu_HU;DISABLE-COMPRESSIONS=1' +# ; +# +# create collation u_cs_compr_disabled +# for utf8 +# from unicode +# case sensitive +# 'LOCALE=hu_HU;DISABLE-COMPRESSIONS=1' +# ; +# create collation u_ci_compr_enabled +# for utf8 +# from unicode +# case insensitive +# 'LOCALE=hu_HU;DISABLE-COMPRESSIONS=0' +# ; +# +# create collation u_cs_compr_enabled +# for utf8 +# from unicode +# case sensitive +# 'LOCALE=hu_HU;DISABLE-COMPRESSIONS=0' +# ; +# create table test ( +# f_cs_compr_disabled varchar(10) collate u_cs_compr_disabled +# ,f_ci_compr_disabled varchar(10) collate u_ci_compr_disabled +# ,f_cs_compr_enabled varchar(10) collate u_cs_compr_enabled +# ,f_ci_compr_enabled varchar(10) collate u_ci_compr_enabled +# ); +# create global temporary table gtt ( +# id smallint generated by default as identity constraint gtt_pk primary key +# ,txt varchar(10) +# ) on commit preserve rows +# ; +# +# set term ^; +# create or alter procedure list_to_rows ( +# A_LST blob sub_type 1 segment size 80, +# A_DEL char(1) = ',') +# returns ( +# LINE integer, +# EOF integer, +# ITEM varchar(8190)) +# AS +# declare pos_ int; +# declare noffset int = 1; +# declare beg int; +# declare buf varchar(8190); +# begin +# -- Splits blob to lines by single char delimiter. +# -- adapted from here: +# -- http://www.sql.ru/forum/actualthread.aspx?bid=2&tid=607154&pg=2#6686267 +# if (a_lst is null) then exit; +# line=0; +# +# while (0=0) do begin +# buf = substring(a_lst from noffset for 30100); +# pos_ = 1; beg = 1; +# while (pos_ <= char_length(buf) and pos_ <= 30000) do begin +# if (substring(buf from pos_ for 1) = :a_del) then begin +# if (pos_ > beg) then +# item = substring(buf from beg for pos_ - beg); +# else +# item = ''; --null; +# suspend; +# line=line+1; +# beg = pos_ + 1; +# end +# pos_ = pos_ + 1; +# end +# if (noffset + pos_ - 2 = char_length(a_lst)) then leave; +# noffset = noffset + beg - 1; +# if (noffset > char_length(a_lst)) then leave; +# end +# +# if (pos_ > beg) then begin +# item = substring(buf from beg for pos_ - beg); +# eof=-1; +# end +# else begin +# item = ''; +# eof=-1; +# end +# suspend; +# +# end +# ^ +# execute block +# as +# declare rowscount int = 1000000; +# --declare rowscount int = 100; +# declare id_min smallint; +# declare id_max smallint; +# declare id_rnd smallint; +# declare i int = 0; +# declare c varchar(10); +# begin +# insert into gtt(txt) select p.item from list_to_rows('c,d,g,l,n,s,t,z,cs,dz,dzs,gy,ly,ny,sz,ty,zs', ',') p; +# select min(id), max(id) from gtt into id_min, id_max; +# while (i < rowscount) do +# begin +# id_rnd = cast( -0.5 + rand() * (0.5 + id_max - id_min) as int ); +# id_rnd = minvalue( maxvalue(id_min,id_rnd), id_max); +# select g.txt from gtt g where g.id = :id_rnd into c; +# insert into test( +# f_cs_compr_disabled +# ,f_ci_compr_disabled +# ,f_cs_compr_enabled +# ,f_ci_compr_enabled +# ) values ( +# :c +# ,:c +# ,:c +# ,:c +# ); +# i = i + 1; +# end +# end +# ^ +# set term ;^ +# commit; +# create index test_cs_compr_disabled on test (f_cs_compr_disabled); +# create index test_ci_compr_disabled on test (f_ci_compr_disabled); +# create index test_cs_compr_enabled on test (f_cs_compr_enabled); +# create index test_ci_compr_enabled on test (f_ci_compr_enabled); +# commit; From 54488c2ac4b3363f859fa089dfc3e6d4b423492a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Dec 2024 14:21:11 +0300 Subject: [PATCH 0290/1064] Added/Updated tests\bugs\gh_6915_test.py: added references to tests which must verify performance issues. See notes. --- tests/bugs/gh_6915_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_6915_test.py b/tests/bugs/gh_6915_test.py index dda69e2e..9e63786a 100644 --- a/tests/bugs/gh_6915_test.py +++ b/tests/bugs/gh_6915_test.py @@ -7,7 +7,11 @@ DESCRIPTION: Only ability to use 'DISABLE-COMPRESSION' in attributes list is checked here. Performance comparison with and without this attribute will be checked in separate test. -FBTEST: bugs.gh_6915 +NOTES: + [24.12.2024] pzotov + Several tests have been added in order to check PERFORMANCE affect of 'DISABLE-COMPRESSIONS=1': + * bugs/gh_6915_cs_cz_test.py + * bugs/gh_6915_hu_hu_test.py """ import pytest From 137566dd24bc495fb94e977f768a6daba7f89816 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:57:56 +0300 Subject: [PATCH 0291/1064] Added/Updated tests\bugs\gh_6915_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_6915_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_6915_test.py b/tests/bugs/gh_6915_test.py index 9e63786a..83c848a9 100644 --- a/tests/bugs/gh_6915_test.py +++ b/tests/bugs/gh_6915_test.py @@ -51,6 +51,7 @@ act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) +@pytest.mark.intl @pytest.mark.version('>=4.0.1') def test_1(act: Action): act.execute() From cb4eb00e47c9926a8e129c28a9de92b20d7c85f2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:58:10 +0300 Subject: [PATCH 0292/1064] Added/Updated tests\bugs\gh_6915_hu_hu_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_6915_hu_hu_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_6915_hu_hu_test.py b/tests/bugs/gh_6915_hu_hu_test.py index 3f975171..f05a7a8d 100644 --- a/tests/bugs/gh_6915_hu_hu_test.py +++ b/tests/bugs/gh_6915_hu_hu_test.py @@ -117,6 +117,7 @@ ; """ +@pytest.mark.intl @pytest.mark.version('>=5.0.0') def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): From 1de210d188494d4069d0bc4a7e594b9638c2f875 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:58:22 +0300 Subject: [PATCH 0293/1064] Added/Updated tests\bugs\gh_6915_cs_cz_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_6915_cs_cz_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_6915_cs_cz_test.py b/tests/bugs/gh_6915_cs_cz_test.py index bd802642..9e68094f 100644 --- a/tests/bugs/gh_6915_cs_cz_test.py +++ b/tests/bugs/gh_6915_cs_cz_test.py @@ -122,6 +122,7 @@ ; """ +@pytest.mark.intl @pytest.mark.version('>=5.0.0') def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): From 6c4ff410f3766928892efc7d12ff4c667ada3f1a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:58:34 +0300 Subject: [PATCH 0294/1064] Added/Updated tests\bugs\gh_7094_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_7094_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_7094_test.py b/tests/bugs/gh_7094_test.py index f1f64620..2f1bfe32 100644 --- a/tests/bugs/gh_7094_test.py +++ b/tests/bugs/gh_7094_test.py @@ -70,6 +70,7 @@ C2 ch """ +@pytest.mark.intl @pytest.mark.version('>=4.0.2') def test_1(act: Action): act.expected_stdout = expected_stdout From 5a7e3b3a007eee31b5dbd5fb921e50ab3e8cf101 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:58:45 +0300 Subject: [PATCH 0295/1064] Added/Updated tests\bugs\gh_7093_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_7093_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_7093_test.py b/tests/bugs/gh_7093_test.py index ba22066b..261d2b97 100644 --- a/tests/bugs/gh_7093_test.py +++ b/tests/bugs/gh_7093_test.py @@ -277,6 +277,7 @@ Records affected: 0 """ +@pytest.mark.intl @pytest.mark.version('>=5.0.0') def test_1(act: Action): act.expected_stdout = expected_stdout From 3a43667f5504472068ab1c050fbb7235f76de4a5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:59:01 +0300 Subject: [PATCH 0296/1064] Added/Updated tests\bugs\gh_7140_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_7140_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_7140_test.py b/tests/bugs/gh_7140_test.py index 552db972..c0296dc8 100644 --- a/tests/bugs/gh_7140_test.py +++ b/tests/bugs/gh_7140_test.py @@ -52,6 +52,7 @@ C1 """ +@pytest.mark.intl @pytest.mark.version('>=4.0.2') def test_1(act: Action): act.expected_stdout = expected_stdout From 250d427e2412929d184c7e8e74f8c4540a9e1d32 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:59:12 +0300 Subject: [PATCH 0297/1064] Added/Updated tests\bugs\gh_6872_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/gh_6872_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_6872_test.py b/tests/bugs/gh_6872_test.py index 7fd93024..9175fa2c 100644 --- a/tests/bugs/gh_6872_test.py +++ b/tests/bugs/gh_6872_test.py @@ -85,6 +85,7 @@ def median(lst): Duration ratio: acceptable. """ +@pytest.mark.intl @pytest.mark.version('>=4.0.1') def test_1(act: Action, capsys): From 306fdc72ac279c0fc24b5f2f897615cb6c901ed6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 09:59:26 +0300 Subject: [PATCH 0298/1064] Added/Updated tests\bugs\core_3947_test.py: Added 'pytest.mark.intl' attribute in order to have ability to run only tests related to i18n --- tests/bugs/core_3947_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_3947_test.py b/tests/bugs/core_3947_test.py index 8afd2661..b59cd3f5 100644 --- a/tests/bugs/core_3947_test.py +++ b/tests/bugs/core_3947_test.py @@ -51,6 +51,7 @@ PLAN SORT (T NATURAL) """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout From be4d4cb2e4c954f3e06c21e3fc7d6465294458ae Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 10:59:32 +0300 Subject: [PATCH 0299/1064] Added/Updated tests\functional\database\create\test_08.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/create/test_08.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/functional/database/create/test_08.py b/tests/functional/database/create/test_08.py index dd781a04..2ace3a43 100644 --- a/tests/functional/database/create/test_08.py +++ b/tests/functional/database/create/test_08.py @@ -4,7 +4,11 @@ ID: create-database-08 TITLE: Create database: Multi file DB DESCRIPTION: Create database with two files. -FBTEST: functional.database.create.08 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -22,7 +26,7 @@ RDB$FILE_LENGTH 300 """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3,<6') def test_1(act: Action): script = f""" create database '{act.db.dsn}' user '{act.db.user}' From a4e9f3dc095ee8e4c3d501cd7f29257292055f8e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 10:59:46 +0300 Subject: [PATCH 0300/1064] Added/Updated tests\functional\database\create\test_09.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/create/test_09.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/functional/database/create/test_09.py b/tests/functional/database/create/test_09.py index 862a862f..d309e2f1 100644 --- a/tests/functional/database/create/test_09.py +++ b/tests/functional/database/create/test_09.py @@ -4,7 +4,11 @@ ID: create-database-09 TITLE: Create database: Multi file DB DESCRIPTION: Create database with four files. -FBTEST: functional.database.create.09 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -30,7 +34,7 @@ RDB$FILE_LENGTH 300 """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3,<6') def test_1(act: Action): script = f""" create database '{act.db.dsn}' user '{act.db.user}' From 4bd66851866651d10f78eb4a5e2fa4b185a6ecd4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 10:59:58 +0300 Subject: [PATCH 0301/1064] Added/Updated tests\functional\database\create\test_10.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/create/test_10.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/functional/database/create/test_10.py b/tests/functional/database/create/test_10.py index d488fbf7..a1ec4e4e 100644 --- a/tests/functional/database/create/test_10.py +++ b/tests/functional/database/create/test_10.py @@ -4,7 +4,11 @@ ID: create-database-10 TITLE: Create database: Multi file DB - starting DESCRIPTION: Database with four files. Additional files specified by STARTING AT. -FBTEST: functional.database.create.10 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -29,7 +33,7 @@ RDB$FILE_LENGTH 0 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0,<6') def test_1(act: Action): script = f""" create database '{act.db.dsn}' user '{act.db.user}' From ff9db383f181263c5f89a6eef4c381ce69b91cab Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 11:33:40 +0300 Subject: [PATCH 0302/1064] Added/Updated tests\functional\database\alter\test_01.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/alter/test_01.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/functional/database/alter/test_01.py b/tests/functional/database/alter/test_01.py index 1fdb86d3..f35bdc81 100644 --- a/tests/functional/database/alter/test_01.py +++ b/tests/functional/database/alter/test_01.py @@ -4,7 +4,11 @@ ID: alter-database-01 TITLE: Alter database: adding a secondary file DESCRIPTION: Adding a secondary file to the database -FBTEST: functional.database.alter.01 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -20,7 +24,7 @@ C:\\JOB\\QA\\FBTEST\\TMP\\TEST.G00 1 10000 0 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0,<6') def test_1(act: Action, capsys): with act.db.connect() as con: with con.cursor() as c: From 62a0c1f7fb08b6502ad20ad5b4d7da6a6d46577b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 11:33:51 +0300 Subject: [PATCH 0303/1064] Added/Updated tests\functional\database\alter\test_02.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/alter/test_02.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/functional/database/alter/test_02.py b/tests/functional/database/alter/test_02.py index 642a6ee7..1bedd276 100644 --- a/tests/functional/database/alter/test_02.py +++ b/tests/functional/database/alter/test_02.py @@ -4,7 +4,11 @@ ID: alter-database-02 TITLE: Alter database: adding secondary file with alternate keyword DESCRIPTION: Adding secondary file with alternate keyword for database. -FBTEST: functional.database.alter.02 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -19,7 +23,7 @@ C:\\JOB\\QA\\FBTEST\\TMP\\TEST.G00 1 10000 0 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0,<6') def test_1(act: Action, capsys): with act.db.connect() as con: with con.cursor() as c: From baa278f259cb821d1ba00c790a02eb49f4086e26 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 11:34:00 +0300 Subject: [PATCH 0304/1064] Added/Updated tests\functional\database\alter\test_03.py: Added restriction for FB 6.x: this test now must be skipped, see commit f0740d2a: Wipe out multi-file database support --- tests/functional/database/alter/test_03.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/functional/database/alter/test_03.py b/tests/functional/database/alter/test_03.py index 952c87c3..b86701aa 100644 --- a/tests/functional/database/alter/test_03.py +++ b/tests/functional/database/alter/test_03.py @@ -5,14 +5,18 @@ TITLE: Alter database: add file with name of this database or previously added files must fail DESCRIPTION: Add same file twice must fail NOTES: - [08.02.2022] pcisar - Fails on Windows with 3.0.8: + [08.02.2022] pcisar + Fails on Windows with 3.0.8: Regex pattern '.*Cannot add file with the same name as the database or added files.*' does not match 'unsuccessful metadata update\n-ALTER DATABASE failed\n-unknown ISC error 336068774'. - [08.04.2022] pzotov - Test PASSES on FB 3.0.8 Rls, 4.0.1 RLs and 5.0.0.467. -FBTEST: functional.database.alter.03 + [08.04.2022] pzotov + Test PASSES on FB 3.0.8 Rls, 4.0.1 RLs and 5.0.0.467. + + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -24,7 +28,7 @@ act = python_act('db') -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0,<6') def test_1(act: Action, capsys): with act.db.connect() as con: with con.cursor() as c: From 4d562f94abeb7c648324487ebfdd1e5ab62d3662 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 11:44:04 +0300 Subject: [PATCH 0305/1064] Added/Updated tests\bugs\core_5704_test.py: Splitted code and expected output for FB versions upto 5.x vs 6.x -- see notes. --- tests/bugs/core_5704_test.py | 79 ++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5704_test.py b/tests/bugs/core_5704_test.py index 4b8bccfe..164e1538 100644 --- a/tests/bugs/core_5704_test.py +++ b/tests/bugs/core_5704_test.py @@ -16,7 +16,15 @@ FBTEST: bugs.core_5704 NOTES: [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). + Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any + statements between them (two semicolon, two carets etc). + + [29.12.2024] pzotov + Splitted code and expected output for FB versions upto 5.x vs 6.x. + FB 6.x does not support statements "alter database add file ..." (issuing 'token unknown: file'). + See: https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") + """ import pytest @@ -30,10 +38,16 @@ act = python_act('db') -expected_stdout = """ +expected_stdout_5x = """ + CHECK_EDS_RESULT 1 + Records affected: 1 + Records affected: 0 CHECK_EDS_RESULT 1 Records affected: 1 Records affected: 0 +""" + +expected_stdout_6x = """ CHECK_EDS_RESULT 1 Records affected: 1 Records affected: 0 @@ -45,7 +59,7 @@ new_main_file = temp_file('new_main_5704.tmp') @pytest.mark.es_eds -@pytest.mark.version('>=3.0.3') +@pytest.mark.version('>=3.0.3,<6') def test_1(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path, new_main_file: Path): eds_script.write_text(f""" @@ -104,6 +118,63 @@ def test_1(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path, method=ShutdownMethod.FORCED, timeout=0) srv.database.bring_online(database=act.db.db_path) # Check - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x + act.stdout = eds_output.read_text() + assert act.clean_stdout == act.clean_expected_stdout + + +@pytest.mark.version('>=6') +def test_2(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path, + new_main_file: Path): + eds_script.write_text(f""" + set count on; + set list on; + set autoddl off; + + set term ^; + create or alter procedure sp_connect returns(check_eds_result int) as + declare usr varchar(31); + declare pwd varchar(31); + declare v_sttm varchar(255) = 'select 1 from rdb$database'; + begin + usr ='{act.db.user}'; + pwd = '{act.db.password}'; + execute statement v_sttm + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user usr password pwd + into check_eds_result; + suspend; + end + ^ + set term ;^ + + commit; + set transaction read committed no record_version lock timeout 1; + + alter database add difference file '{new_diff_file}'; + select * from sp_connect; + + rollback; + select * from rdb$files; + rollback; + + """) + # + with open(eds_output, mode='w') as eds_out: + p_eds_sql = subprocess.Popen([act.vars['isql'], '-i', str(eds_script), + '-user', act.db.user, + '-password', act.db.password, act.db.dsn], + stdout=eds_out, stderr=subprocess.STDOUT) + try: + time.sleep(4) + finally: + p_eds_sql.terminate() + # Ensure that database is not busy + with act.connect_server() as srv: + srv.database.shutdown(database=act.db.db_path, mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + srv.database.bring_online(database=act.db.db_path) + # Check + act.expected_stdout = expected_stdout_6x act.stdout = eds_output.read_text() assert act.clean_stdout == act.clean_expected_stdout From 4af274b8e881545ddaeeae54c7460d871c166bc2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Dec 2024 11:47:54 +0300 Subject: [PATCH 0306/1064] Added/Updated tests\functional\shadow\test_create_02.py: Added restriction for FB 6.x: this test now must be skipped since implemented GH-8047 (Wipe out multi-file database support) --- tests/functional/shadow/test_create_02.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/functional/shadow/test_create_02.py b/tests/functional/shadow/test_create_02.py index 06828193..2214e1b2 100644 --- a/tests/functional/shadow/test_create_02.py +++ b/tests/functional/shadow/test_create_02.py @@ -2,9 +2,13 @@ """ ID: shadow.create-02 -TITLE: CREATE SHADOW +TITLE: CREATE SHADOW: check usage with presense of 'FILE <...>' clause. DESCRIPTION: -FBTEST: functional.shadow.create_02 +NOTES: + [29.12.2024] pzotov + Added restriction for FB 6.x: this test now must be skipped, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") """ import pytest @@ -47,7 +51,7 @@ Records affected: 2 """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3,<6') def test_1(act: Action): act.expected_stdout = expected_stdout act.execute() From eb019319e555ef1daefd3b5e314705a5c73db555 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Dec 2024 12:02:31 +0300 Subject: [PATCH 0307/1064] Added/Updated tests\bugs\core_5630_test.py: splitted expected output for 6.x since some columns in rdb$files now have NULLS instead of zeroes - see notes. --- tests/bugs/core_5630_test.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_5630_test.py b/tests/bugs/core_5630_test.py index d89cf2b7..cfba5cd2 100644 --- a/tests/bugs/core_5630_test.py +++ b/tests/bugs/core_5630_test.py @@ -4,10 +4,15 @@ ID: issue-5896 ISSUE: 5896 TITLE: Can't create the shadow file -DESCRIPTION: - Shadow file is can not be created during restore when -use_all_space option is used +DESCRIPTION: Shadow file can not be created during restore when '-use_all_space' option is used JIRA: CORE-5630 -FBTEST: bugs.core_5630 +NOTES: + [30.12.2024] pzotov + Splitted expected out for FB 6.x because columns rdb$file_sequence, rdb$file_start and rdb$file_length + have NULLs instead of zeroes, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") + Checked on 6.0.0.565 """ import locale @@ -17,24 +22,24 @@ db = db_factory() -act = python_act('db', substitutions=[('Commit current transaction \\(y/n\\)\\?', '')]) +act = python_act('db', substitutions=[('[ \t]+', ' ')]) -expected_stdout_a = """ +expected_stdout_5x = """ RDB$FILE_SEQUENCE 0 RDB$FILE_START 0 RDB$FILE_LENGTH 0 RDB$FILE_FLAGS 1 RDB$SHADOW_NUMBER 1 - S_HASH_BEFORE 1499836372373901520 + S_HASH 1499836372373901520 """ -expected_stdout_b = """ - RDB$FILE_SEQUENCE 0 - RDB$FILE_START 0 - RDB$FILE_LENGTH 0 +expected_stdout_6x = """ + RDB$FILE_SEQUENCE + RDB$FILE_START + RDB$FILE_LENGTH RDB$FILE_FLAGS 1 RDB$SHADOW_NUMBER 1 - S_HASH_AFTER 1499836372373901520 + S_HASH 1499836372373901520 """ fdb_file = temp_file('core_5630.fdb') @@ -70,11 +75,11 @@ def test_1(act: Action, fdb_file: Path, fbk_file: Path, shd_file: Path): commit; set list on; select * from v_shadow_info; - select hash( list(s) ) as s_hash_before from test; + select hash( list(s) ) as s_hash from test; quit; """ - act.expected_stdout = expected_stdout_a + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=['-q'], input = init_ddl, connect_db=False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout # @@ -94,12 +99,12 @@ def test_1(act: Action, fdb_file: Path, fbk_file: Path, shd_file: Path): sql_text = """ set list on; select * from v_shadow_info; - select hash( list(s) ) as s_hash_after from test; + select hash( list(s) ) as s_hash from test; """ act.reset() #----------------------------------------------------------------------------------- - act.expected_stdout = expected_stdout_b + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=['-q', act.get_dsn(fdb_file)], input=sql_text, connect_db=False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From fab53758ab4fee628fd3a6602a40f28dbccaee23 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Dec 2024 12:05:43 +0300 Subject: [PATCH 0308/1064] Added/Updated tests\functional\shadow\test_create_01.py: splitted expected output for 6.x since some columns in rdb$files now have NULLS instead of zeroes - see notes. --- tests/functional/shadow/test_create_01.py | 26 ++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/functional/shadow/test_create_01.py b/tests/functional/shadow/test_create_01.py index 195dab2b..ea6be873 100644 --- a/tests/functional/shadow/test_create_01.py +++ b/tests/functional/shadow/test_create_01.py @@ -2,9 +2,15 @@ """ ID: shadow.create-01 -TITLE: CREATE SHADOW +TITLE: CREATE SHADOW: check basic usage DESCRIPTION: -FBTEST: functional.shadow.create_01 +NOTES: + [30.12.2024] pzotov + Splitted expected out for FB 6.x because columns rdb$file_sequence, rdb$file_start and rdb$file_length + have NULLs instead of zeroes, see: + https://github.com/FirebirdSQL/firebird/commit/f0740d2a3282ed92a87b8e0547139ba8efe61173 + ("Wipe out multi-file database support (#8047)") + Checked on 6.0.0.565 """ import pytest @@ -34,9 +40,9 @@ from rdb$files; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) -expected_stdout = """ +expected_stdout_5x = """ CHECK_SHD_FILE_NAME OK FILE_SEQUENCE 0 FILE_START 0 @@ -46,8 +52,18 @@ Records affected: 1 """ +expected_stdout_6x = """ + CHECK_SHD_FILE_NAME OK + FILE_SEQUENCE + FILE_START + FILE_LENGTH + FILE_FLAGS 1 + SHADOW_NUMBER 1 + Records affected: 1 +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute() assert act.clean_stdout == act.clean_expected_stdout From b2a5bd43cab9bc10bedf628f7b7c27514aeb8353 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Dec 2024 12:13:09 +0300 Subject: [PATCH 0309/1064] Added/Updated tests\bugs\gh_6915_test.py: added comments --- tests/bugs/gh_6915_test.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_6915_test.py b/tests/bugs/gh_6915_test.py index 83c848a9..2754e794 100644 --- a/tests/bugs/gh_6915_test.py +++ b/tests/bugs/gh_6915_test.py @@ -5,8 +5,11 @@ ISSUE: 6915 TITLE: Allow attribute DISABLE-COMPRESSIONS in UNICODE collations DESCRIPTION: - Only ability to use 'DISABLE-COMPRESSION' in attributes list is checked here. - Performance comparison with and without this attribute will be checked in separate test. + Original discussion: + https://sourceforge.net/p/firebird/mailman/firebird-devel/thread/9361c612-d720-eb76-d412-7101518ca60d%40ibphoenix.cz/ + + Only ability to use 'DISABLE-COMPRESSION' in attributes list is checked here. + Performance comparison with and without this attribute will be checked in separate test. NOTES: [24.12.2024] pzotov Several tests have been added in order to check PERFORMANCE affect of 'DISABLE-COMPRESSIONS=1': From 6c5b05bfdc76a5d13465afab8e0abe6164f050e3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Dec 2024 12:13:18 +0300 Subject: [PATCH 0310/1064] Added/Updated tests\bugs\gh_6915_cs_cz_test.py: added comments --- tests/bugs/gh_6915_cs_cz_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/bugs/gh_6915_cs_cz_test.py b/tests/bugs/gh_6915_cs_cz_test.py index 9e68094f..c46137e2 100644 --- a/tests/bugs/gh_6915_cs_cz_test.py +++ b/tests/bugs/gh_6915_cs_cz_test.py @@ -5,6 +5,8 @@ ISSUE: https://github.com/FirebirdSQL/firebird/issues/6915 TITLE: Performance effect of applying 'DISABLE-COMPRESSIONS=1' in UNICODE collation for LOCALE=cs_CZ DESCRIPTION: + Original discussion: + https://sourceforge.net/p/firebird/mailman/firebird-devel/thread/9361c612-d720-eb76-d412-7101518ca60d%40ibphoenix.cz/ Test verifies only PERFORMANCE issues referred to in the ticket #6915. Correctness of ORDER BY is not checked. A pre-build database is used for check, see: files/gh_6915_cs_cz.zip (it was created in FB 4.x with date ~aug-2021). SQL script that was used to fulfill test DB see in the end of this file. From ba2fe0f29273b4747e5fc0ec6d885aa138a0bfb2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Dec 2024 12:13:29 +0300 Subject: [PATCH 0311/1064] Added/Updated tests\bugs\gh_6915_hu_hu_test.py: added comments --- tests/bugs/gh_6915_hu_hu_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/bugs/gh_6915_hu_hu_test.py b/tests/bugs/gh_6915_hu_hu_test.py index f05a7a8d..52553b1b 100644 --- a/tests/bugs/gh_6915_hu_hu_test.py +++ b/tests/bugs/gh_6915_hu_hu_test.py @@ -5,6 +5,8 @@ ISSUE: https://github.com/FirebirdSQL/firebird/issues/6915 TITLE: Performance effect of applying 'DISABLE-COMPRESSIONS=1' in UNICODE collation for LOCALE=hu_HU DESCRIPTION: + Original discussion: + https://sourceforge.net/p/firebird/mailman/firebird-devel/thread/9361c612-d720-eb76-d412-7101518ca60d%40ibphoenix.cz/ Test verifies only PERFORMANCE issues referred to in the ticket #6915. Correctness of ORDER BY is not checked. A pre-build database is used for check, see: files/gh_6915_hu_hu.zip (it was created in FB 4.x with date 31-jul-2021). Hungarian alphabet uses several digraphs and one trigraph: cs,dz,dzs,gy,ly,ny,sz,ty,zs. From 35aedb2690d3288bad6147b3532b73cec1386087 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 31 Dec 2024 11:43:04 +0300 Subject: [PATCH 0312/1064] Added/Updated tests\bugs\core_4321_test.py: Added forgotten semicolon after 'SET LIST ON'. --- tests/bugs/core_4321_test.py | 68 ++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/tests/bugs/core_4321_test.py b/tests/bugs/core_4321_test.py index af43f41a..60e2c660 100644 --- a/tests/bugs/core_4321_test.py +++ b/tests/bugs/core_4321_test.py @@ -6,7 +6,12 @@ TITLE: Regression: ISQL does not destroy the SQL statement DESCRIPTION: JIRA: CORE-4321 -FBTEST: bugs.core_4321 +NOTES: + [31.12.2024] pzotov + Added forgotten semicolon after 'SET LIST ON'. + Parsing problem appeared on 6.0.0.0.570 after d6ad19aa07deeaac8107a25a9243c5699a3c4ea1 + ("Refactor ISQL creating FrontendParser class"). + It looks weird how it could work w/o 'token unknown / list' all this time in all major FB versions :-) """ import pytest @@ -16,54 +21,55 @@ test_script = """ -- NB: 2.1.7 FAILED, output contains '4' for select count(*) ... - set list on - select 1 x from rdb$database; - select 1 x from rdb$database; - select 1 x from rdb$database; - select 1 x from rdb$database; + set list on; + select /* tag_for_watch */ 1 point_a from rdb$database; + select /* tag_for_watch */ 1 point_a from rdb$database; + select /* tag_for_watch */ 1 point_a from rdb$database; + select /* tag_for_watch */ 1 point_a from rdb$database; - select count(*) c from mon$statements s - where s.mon$sql_text containing 'select 1 x' -- 08-may-2017: need for 4.0 Classic! Currently there is also query with RDB$AUTH_MAPPING data in mon$statements + select count(*) count_after_point_a from mon$statements s + where s.mon$sql_text containing '/* tag_for_watch */' ; commit; - select count(*) c from mon$statements s - where s.mon$sql_text containing 'select 1 x' + select count(*) count_after_commit_a from mon$statements s + where s.mon$sql_text containing '/* tag_for_watch */' ; - select 1 x from rdb$database; - select 1 x from rdb$database; - select 1 x from rdb$database; - select 1 x from rdb$database; + select /* tag_for_watch */ 1 point_b from rdb$database; + select /* tag_for_watch */ 1 point_b from rdb$database; + select /* tag_for_watch */ 1 point_b from rdb$database; + select /* tag_for_watch */ 1 point_b from rdb$database; - select count(*) c from mon$statements s - where s.mon$sql_text containing 'select 1 x' + select count(*) count_after_point_b from mon$statements s + where s.mon$sql_text containing '/* tag_for_watch */' ; commit; - select count(*) c from mon$statements s - where s.mon$sql_text containing 'select 1 x' + select count(*) count_after_commit_b from mon$statements s + where s.mon$sql_text containing '/* tag_for_watch */' ; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')] ) expected_stdout = """ - X 1 - X 1 - X 1 - C 1 - C 1 - X 1 - X 1 - X 1 - X 1 - C 1 - C 1 + POINT_A 1 + POINT_A 1 + POINT_A 1 + POINT_A 1 + COUNT_AFTER_POINT_A 1 + COUNT_AFTER_COMMIT_A 1 + POINT_B 1 + POINT_B 1 + POINT_B 1 + POINT_B 1 + COUNT_AFTER_POINT_B 1 + COUNT_AFTER_COMMIT_B 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 2ac5ddf343df1368e0dc61027cfd985b5971ee1f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 31 Dec 2024 16:55:55 +0300 Subject: [PATCH 0313/1064] Added/Updated tests\bugs\core_1142_test.py: Removed 'SHOW' command because its output can change during intensive development. Fixed https://github.com/FirebirdSQL/firebird-qa/pull/33/files --- tests/bugs/core_1142_test.py | 69 +++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_1142_test.py b/tests/bugs/core_1142_test.py index 4e434773..946ce1a3 100644 --- a/tests/bugs/core_1142_test.py +++ b/tests/bugs/core_1142_test.py @@ -6,37 +6,74 @@ TITLE: Cannot alter generator's comment to the same value DESCRIPTION: JIRA: CORE-1142 -FBTEST: bugs.core_1142 +NOTES: + [31.12.2024] pzotov + Removed 'SHOW' command because its output can change during intensive development. + Also, 'SHOW COMMENT ON ' is not valid in ISQL, see: + https://github.com/FirebirdSQL/firebird-qa/pull/33/files + + Parsing problem appeared on 6.0.0.0.570 after d6ad19aa07deeaac8107a25a9243c5699a3c4ea1 + ("Refactor ISQL creating FrontendParser class"). + + Checked on 6.0.0.570, 5.0.2.1583 """ import pytest from firebird.qa import * -init_script = """create generator T;""" +GEN_NAME = 'TEST_GEN' + +init_script = f""" + create generator {GEN_NAME}; + create view v_show_gen_descr as + select g.rdb$description as descr_blob_id + from rdb$generators g + where g.rdb$generator_name = '{GEN_NAME.upper()}'; + commit; +""" db = db_factory(init=init_script) -test_script = """comment on generator T is 'comment'; -commit; -show comment on generator T; -comment on generator T is 'comment'; -commit; -show comment on generator T; -comment on generator T is 'different comment'; -commit; -show comment on generator T; +test_script = f""" + set blob all; + set list on; + set count on; + comment on generator {GEN_NAME} is 'comment N1'; + commit; + select * from v_show_gen_descr; + + comment on generator {GEN_NAME} is 'comment N1'; + commit; + select * from v_show_gen_descr; + + comment on generator {GEN_NAME} is 'comment N11'; + commit; + select * from v_show_gen_descr; + + comment on generator {GEN_NAME} is 'comment N11'; + commit; + select * from v_show_gen_descr; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' '), ('DESCR_BLOB_ID .*', '')]) + +expected_stdout = """ + comment N1 + Records affected: 1 + + comment N1 + Records affected: 1 + + comment N11 + Records affected: 1 -expected_stdout = """COMMENT ON GENERATOR T IS comment; -COMMENT ON GENERATOR T IS comment; -COMMENT ON GENERATOR T IS different comment; + comment N11 + Records affected: 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 4634414e66cdaf692a86d30ed84973ba83be4126 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 31 Dec 2024 18:12:08 +0300 Subject: [PATCH 0314/1064] Added/Updated tests\bugs\gh_7106_test.py: User names with delimiting character must be enclosed in double quotes since 6.0.0.570. SEE NOTES. --- tests/bugs/gh_7106_test.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_7106_test.py b/tests/bugs/gh_7106_test.py index fa86fe54..6f079473 100644 --- a/tests/bugs/gh_7106_test.py +++ b/tests/bugs/gh_7106_test.py @@ -26,6 +26,17 @@ Explanation by Alex with example: letter 06.03.2023 18:58 Confirmed problem on 5.0.0.376 (with user name 'test-user') Checked on 5.0.0.379, 5.0.0.970, 4.0.3.2904, 3.0.11.33665 -- all OK. + + [31.12.2024] pzotov + User names with delimiting character must be enclosed in double quotes since 6.0.0.570 otherwise we get + "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log for details" and firebird.log + will contain: + Authentication error cannot attach to password database + Error in isc_compile_request() API call when working + with legacy security database table PLG$USERS is not defined + + Parsing problem appeared on 6.0.0.0.570 after d6ad19aa07deeaac8107a25a9243c5699a3c4ea1 + ("Refactor ISQL creating FrontendParser class"). """ import os @@ -161,23 +172,23 @@ def test_1(act: Action, capsys): for use_connect_sttm in (True,False,): - for u in CHECKED_NAMES: + for u_name in CHECKED_NAMES: isql_connect_sttm = \ '\n'.join( ( 'set bail on;', 'set heading off;', - f"connect 'localhost:{REQUIRED_ALIAS}' user {u} password '123';" if use_connect_sttm else "", + f"""connect 'localhost:{REQUIRED_ALIAS}' user "{u_name}" password '123';""" if use_connect_sttm else "", 'select mon$user from mon$attachments a where a.mon$attachment_id = current_connection;' ) ) - act.expected_stdout = u + act.expected_stdout = u_name if use_connect_sttm: # Try to make connection using isql CONNECT operator: act.isql(switches = ['-q'], input = isql_connect_sttm, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) else: # try to make connection via command-line argument "-user ...": - act.isql(switches = ['-q', '-user', u, '-pas', '123', f'localhost:{REQUIRED_ALIAS}'], input = isql_connect_sttm, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) - assert act.clean_stdout == act.clean_expected_stdout, f'User "{u}" could not make connection using isql {"" if use_connect_sttm else " -user ... -pas ..."} and script:\n{isql_connect_sttm}' + act.isql(switches = ['-q', '-user', f'"{u_name}"', '-pas', '123', f'localhost:{REQUIRED_ALIAS}'], input = isql_connect_sttm, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout, f'User "{u_name}" could not make connection using isql {"" if use_connect_sttm else " -user ... -pas ..."} and script:\n{isql_connect_sttm}' act.reset() act.gfix(switches = [ '-shut', 'full', '-force', '0', f'localhost:{REQUIRED_ALIAS}', '-user', act.db.user, '-pas', act.db.password ], credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) From 3bbf0047ba9f645e37bc6ba31dec821f6af4d23a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 13 Jan 2025 13:12:28 +0300 Subject: [PATCH 0315/1064] 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. --- tests/bugs/core_2650_test.py | 334 ++++++++++++++++++++++++++++++++++- 1 file changed, 327 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_2650_test.py b/tests/bugs/core_2650_test.py index 2836dea3..2dfd5d87 100644 --- a/tests/bugs/core_2650_test.py +++ b/tests/bugs/core_2650_test.py @@ -17,7 +17,7 @@ JIRA: CORE-2650 FBTEST: bugs.core_2650 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. 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" @@ -37,6 +37,13 @@ https://github.com/FirebirdSQL/firebird/commit/901b4ced9a3615929e0027d42ebb2392e943b205 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 @@ -212,11 +219,6 @@ } -test_script = """ - set plan on; - set explain on; -""" - ############################################################################### fb4x_expected_out = f""" @@ -859,6 +861,316 @@ ........-> 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 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') #----------------------------------------------------------- @@ -872,6 +1184,14 @@ def replace_leading(source, char="."): @pytest.mark.version('>=4.0') def test_1(act: Action, capsys): 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() for q_idx, q_tuple in query_map.items(): 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')]) ) 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 assert act.clean_stdout == act.clean_expected_stdout From f869ab0158c9bb159b7fca89fb3090ccfb9a3368 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 13 Jan 2025 14:26:41 +0300 Subject: [PATCH 0316/1064] Added/Updated tests\bugs\core_4218_test.py: Added (temporary ?) 'credentials = False' to prevent ISQL from using '-USER ... -PASS ...'. IMO, this is bug; see https://github.com/FirebirdSQL/firebird/issues/8385 --- tests/bugs/core_4218_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4218_test.py b/tests/bugs/core_4218_test.py index 41c85a13..682801f2 100644 --- a/tests/bugs/core_4218_test.py +++ b/tests/bugs/core_4218_test.py @@ -6,9 +6,17 @@ TITLE: Add database owner to mon$database DESCRIPTION: JIRA: CORE-4218 -FBTEST: bugs.core_4218 +NOTES: + [13.01.2025] pzotov + Added (temporary ?) 'credentials = False' to prevent ISQL from using '-USER ... -PASS ...'. + This is needed since 6.0.0.570, otherwise we get (on attempting to create DB): + Statement failed, SQLSTATE = 28000 + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + -Different logins in connect and attach packets - client library error + (IMO, this is bug; see https://github.com/FirebirdSQL/firebird/issues/8385) """ - +import time +import locale import pytest from pathlib import Path from firebird.qa import * @@ -25,27 +33,29 @@ def test_1(act: Action, tmp_user: User, test_db: Path): with act.db.connect() as con: c = con.cursor() - c.execute('grant create database to user TMP_U4218') + c.execute(f'grant create database to user {tmp_user.name}') con.commit() test_script = f""" + -- set echo on; create database 'localhost:{test_db}' user {tmp_user.name} password '{tmp_user.password}'; set list on; select current_user as who_am_i, mon$owner as who_is_owner from mon$database; commit; - connect 'localhost:{test_db}'; + connect 'localhost:{test_db}' user {act.db.user} password '{act.db.password}'; select current_user as who_am_i, mon$owner as who_is_owner from mon$database; commit; drop database; quit; """ + expected_stdout = f""" WHO_AM_I {tmp_user.name.upper()} WHO_IS_OWNER {tmp_user.name.upper()} - WHO_AM_I SYSDBA + WHO_AM_I {act.db.user} WHO_IS_OWNER {tmp_user.name.upper()} """ act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input=test_script, connect_db=False, combine_output = True) + act.isql(switches=['-q'], input=test_script, connect_db=False, combine_output = True, credentials = False, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From ef33e8f8a6a6d0d0d30b5261cf66e7e6396ee72c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 13 Jan 2025 14:44:35 +0300 Subject: [PATCH 0317/1064] Added/Updated tests\functional\database\create\test_02.py: Added (temporary ?) 'credentials = False' to prevent ISQL from using '-USER ... -PASS ...'. IMO, this is bug; see https://github.com/FirebirdSQL/firebird/issues/8385 --- tests/functional/database/create/test_02.py | 95 +++++++++++---------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/tests/functional/database/create/test_02.py b/tests/functional/database/create/test_02.py index 7170abf1..907183cb 100644 --- a/tests/functional/database/create/test_02.py +++ b/tests/functional/database/create/test_02.py @@ -5,60 +5,67 @@ TITLE: Create database: non sysdba user DESCRIPTION: FBTEST: functional.database.create.02 +NOTES: + [13.01.2025] pzotov + Added (temporary ?) 'credentials = False' to prevent ISQL from using '-USER ... -PASS ...'. + This is needed since 6.0.0.570, otherwise we get (on attempting to create DB): + Statement failed, SQLSTATE = 28000 + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + -Different logins in connect and attach packets - client library error + (IMO, this is bug; see https://github.com/FirebirdSQL/firebird/issues/8385) """ +import locale +from pathlib import Path import pytest from firebird.qa import * db = db_factory() +act = python_act('db', substitutions = [('[ \t]+', ' ')]) -test_script = """ - set wng off; - set bail on; - create or alter user ozzy password 'osb' revoke admin role; - commit; - revoke all on all from ozzy; - commit; +tmp_user = user_factory('db', name='tmp$boss', password='123') +test_db = temp_file('tmp4test.fdb') - -- ::: NB ::: do NOT miss specification of 'USER' or 'ROLE' clause in - -- GRANT | REVOKE CREATE DATABASE, between `to` and login! Otherwise: - -- Statement failed, SQLSTATE = 0A000 - -- unsuccessful metadata update - -- -GRANT failed - -- -feature is not supported - -- -Only grants to USER or ROLE are supported for CREATE DATABASE - grant create database to USER ozzy; - -- ^^^^ - grant drop database to USER ozzy; - -- ^^^^ - commit; - - create database 'localhost:$(DATABASE_LOCATION)tmp.ozzy$db$987456321.tmp' user 'OZZY' password 'osb'; - - set list on; - select - a.mon$user "Who am I ?" - ,iif( m.mon$database_name containing 'tmp.ozzy$db$987456321.tmp' , 'YES', 'NO! ' || m.mon$database_name) "Am I on just created DB ?" - from mon$database m, mon$attachments a where a.mon$attachment_id = current_connection; - commit; +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User, test_db: Path): - drop database; - connect '$(DSN)' user 'SYSDBA' password 'masterkey'; - revoke create database from user ozzy; - revoke drop database from user ozzy; - drop user ozzy; - commit; -""" + test_script = f""" + set wng off; + set bail on; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + revoke all on all from {tmp_user.name}; + commit; -act = isql_act('db', test_script) + -- ::: NB ::: do NOT miss specification of 'USER' or 'ROLE' clause in + -- GRANT | REVOKE CREATE DATABASE, between `to` and login! Otherwise: + -- Statement failed, SQLSTATE = 0A000 + -- unsuccessful metadata update + -- -GRANT failed + -- -feature is not supported + -- -Only grants to USER or ROLE are supported for CREATE DATABASE + grant create database to USER {tmp_user.name}; + -- ^^^^ + grant drop database to USER {tmp_user.name}; + -- ^^^^ + commit; + create database 'localhost:{test_db}' user {tmp_user.name} password '{tmp_user.password}'; -expected_stdout = """ - Who am I ? OZZY - Am I on just created DB ? YES -""" + set list on; + select + a.mon$user "Who am I ?" + ,iif( m.mon$database_name containing '{test_db}' , 'YES', 'NO! ' || m.mon$database_name) "Am I on just created DB ?" + from mon$database m cross join mon$attachments a + where a.mon$attachment_id = current_connection; + commit; + drop database; + set echo on; + -- Done. + """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = f""" + Who am I ? {tmp_user.name.upper()} + Am I on just created DB ? YES + -- Done. + """ + act.isql(switches=['-q'], input=test_script, connect_db=False, combine_output = True, credentials = False, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From afdd829546b40dd18d391ec2af06f458017601c3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 15 Jan 2025 10:50:19 +0300 Subject: [PATCH 0318/1064] Added/Updated tests\bugs\gh_8379_test.py: Only FB-6.x can be checked, see notes. Checked on 6.0.0.577 - all OK. --- tests/bugs/gh_8379_test.py | 128 +++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 tests/bugs/gh_8379_test.py diff --git a/tests/bugs/gh_8379_test.py b/tests/bugs/gh_8379_test.py new file mode 100644 index 00000000..a012b991 --- /dev/null +++ b/tests/bugs/gh_8379_test.py @@ -0,0 +1,128 @@ +#coding:utf-8 + +""" +ID: issue-8379 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8379 +TITLE: Incorrect cardinality estimation for retrievals with multiple compound indices having common set of fields +DESCRIPTION: + +NOTES: + [15.01.2025] pzotov + + 1. This ticket can NOT be checked on FB 5.x: there are no differences neither in explained plans nor in trace statistics + for snapshots before and after fix. Only cardinality estimation can be checked but this feature avaliable only in FB-6 + via rdb$sql.explain() package (see doc/sql.extensions/README.sql_package.md). + 2. Cardinality change can be seen only for second example provided in the ticket + ("Test #2: three conditions, two of them are mapped ... the third one is not mapped to an index") + // see also letter from dimitr 14.01.2025 15:06 + + 3. Query : + select + plan_line as p_line + ,cardinality + ,access_path + from rdb$sql.explain(q'# + select count(*) as cnt_1 + from t + where f1 = 99 and f2 = 99 and f3 = 99 + #') + - must return rows with *different* cardinality for plan lines with "Filter" and "Table ... Access By ID": + P_LINE CARDINALITY ACCESS_PATH | + 1 Select expression | + 2 1 -> Aggregate | + 3 1.78675004326506 -> Filter | <<< THIS VALUE MUST BE MUCH LESS THAN ONE FOR P_LINE = 4 ('card_afte') + 4 17.8675004326506 -> Table ... Access By ID | <<< THIS IS VALUE BEFORE 'FILTER' IS APPLIED ('card_befo') + Before fix this was not so: cardinality value in line with "Filter" was the same as in line for "Table ... Access By ID": + Thanks to dimitr for suggestions. + + Confirmed bug on 6.0.0.576. + Checked on 6.0.0.577 - all OK. +""" + +import pytest +from firebird.qa import * + +############# +N_ROWS = 5000 +OK_MSG = 'Cardinality estimation: EXPECTED.' +############# + +init_script = f""" + recreate view v_check_card as select 1 x from rdb$database; + recreate table test (id int primary key, f1 int, f2 int, f3 int); + + set term ^; + execute block as + declare n int = {N_ROWS}; + declare i int = 0; + begin + while (i < n) do + begin + insert into test(id, f1, f2, f3) values(:i, mod(:i, 100), mod(:i, 200), mod(:i, 300)); + i = i + 1; + end + end + ^ + set term ;^ + commit; + + create index it1 on test(f1, f2); + create index it2 on test(f1, f3); + commit; + + recreate view v_check_card as + with + a as ( + select + plan_line + ,record_source_id + ,parent_record_source_id + ,level + ,cardinality + ,record_length + ,key_length + ,access_path + from rdb$sql.explain(q'# + select count(*) as cnt_1 + from test + where f1 = 99 and f2 = 99 and f3 = 99 + #') + ) + ,b as ( + select + a.plan_line + ,a.cardinality as card_afte + ,lead(a.cardinality)over(order by a.plan_line) card_befo + ,a.access_path + from a + ) + select + iif( b.card_afte / nullif(b.card_befo,0) < 1 + ,'{OK_MSG}' + ,'Cardinality estimation INCORRECT, HAS NOT REDUCED: ' + || 'card_befo = ' || b.card_befo + || ', card_afte = ' || b.card_afte + || ', card_afte / card_befo = ' || (b.card_afte / nullif(b.card_befo,0)) + ) as msg + from b + where b.access_path containing 'filter'; +""" + +db = db_factory(init=init_script) + +test_script = """ + set heading off; + select * from v_check_card; +""" + +act = isql_act('db', test_script) + +expected_stdout = f""" + {OK_MSG} +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From aab05ab88b7d5ff01a3e0033b1a208bd16cf559e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 15 Jan 2025 21:06:33 +0300 Subject: [PATCH 0319/1064] Added/Updated tests\bugs\gh_8265_test.py: CRITICAL ISSUE. Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY before PS will be freed. See notes. --- tests/bugs/gh_8265_test.py | 45 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8265_test.py b/tests/bugs/gh_8265_test.py index 891e0d76..567bf7a0 100644 --- a/tests/bugs/gh_8265_test.py +++ b/tests/bugs/gh_8265_test.py @@ -17,6 +17,38 @@ Confirmed problem on 5.0.2.1516-fe6ba50 (23.09.2024). Checked on 5.0.2.1516-92316F0 (25.09.2024). + + [15.01.2025] pzotov + + ### CRITICAL ISSUE ### PROBABLY MUST BE APPLIED TO ALL TESTS WITH SIMILAR BEHAVOUR ### + + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises. + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + + Example of broken pytest log when AV occurs: + ========== + tests/bugs/gh_8265_test.py::test_1 Windows fatal exception: access violation + + Current thread 0x0000385c (most recent call first): + Garbage-collecting + File "C:/Python3x/Lib/site-packages/firebird/driver/interfaces.py", line 831 in free + File "C:/Python3x/Lib/site-packages/firebird/driver/core.py", line 2736 in free + ... + File "C:/Python3x/Scripts/pytest.exe/__main__.py", line 7 in + File "", line 88 in _run_code + File "", line 198 in _run_module_as_main + PASSED [1773/2565] + ========== + The reason of that was explained by Vlad, letter 26.10.24 17:42 + (subject: "oddities when use instances of selective statements"): + * line 'cur1.execute(ps1)' creates a new cursor but looses reference on it; + * but this cursor is linked with instance of ps1 which *has* reference on that cursor; + * call 'ps1.free()' delete this anonimous cursor but Python runtime + (or - maybe - code that makes connection cleanup) does not know about it + and tries to delete this anon cursor AGAIN when code finishes 'with' block. + This attempt causes AV. """ import pytest @@ -117,24 +149,33 @@ def test_1(act: Action, capsys): with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: for idx, test_sql in enumerate(test_query_lst): + ps,rs = None, None try: cur = con.cursor() cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") for r in cur: print(r[0],r[1]) + ps = cur.prepare(test_sql) print(f'\nExample {idx+1}') # Print explained plan with padding eash line by dots in order to see indentations: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - # Print data: - for r in cur.execute(ps): + # explained by hvlad, 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + # Print data: print(r[0]) except DatabaseError as e: print(e.__str__()) print(e.gds_codes) + finally: + if rs: + rs.close() + if ps: + ps.free() act.expected_stdout = f""" SubQueryConversion true From 621bc55e2a84bb06206b28a2b99755b08ee6949b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 Jan 2025 08:44:36 +0300 Subject: [PATCH 0320/1064] Added/Updated tests\bugs\core_2650_test.py: Changed expected_out for FB 5.x after e24e0 2025.01.13. See notes. --- tests/bugs/core_2650_test.py | 180 +++++++++++++++++------------------ 1 file changed, 86 insertions(+), 94 deletions(-) diff --git a/tests/bugs/core_2650_test.py b/tests/bugs/core_2650_test.py index 2dfd5d87..88d0745d 100644 --- a/tests/bugs/core_2650_test.py +++ b/tests/bugs/core_2650_test.py @@ -43,7 +43,11 @@ 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 + [16.01.2025] pzotov + 8. Changed expected_out for FB 5.x after e24e0 2025.01.13 ("More correct plan output for subqueries generated during NOT IN transformation"). + Despite that now expected_out strings for 5.x and 6.x become equal, they remain separated in case of future changes in 6.x+ + + Checked 6.0.0.573-c20f37a; 5.0.2.1592-2d11769 """ import pytest @@ -544,47 +548,42 @@ fb5x_expected_out = f""" 1000 - {query_map[1000][0]} - {query_map[1000][1]} + 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 - {query_map[1010][0]} - {query_map[1010][1]} + 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 - {query_map[1020][0]} - {query_map[1020][1]} + select txt_short from test a03 order by id rows 1 + MUST use refetch regardless on length of column because ROWS presents Select Expression ....-> First N Records ........-> Refetch ............-> Sort (record length: 28, key length: 8) ................-> Table "TEST" as "A03" Full Scan - 2000 - {query_map[2000][0]} - {query_map[2000][1]} + 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 - {query_map[2010][0]} - {query_map[2010][1]} + 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 - {query_map[3000][0]} - {query_map[3000][1]} + 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) @@ -593,10 +592,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A04" Full Scan - 3010 - {query_map[3010][0]} - {query_map[3010][1]} + 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 @@ -606,31 +604,29 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A05" Full Scan - 3020 - {query_map[3020][0]} - {query_map[3020][1]} - Select Expression + 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 - Select Expression + 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 - {query_map[3030][0]} - {query_map[3030][1]} - Select Expression + 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 - Select Expression + Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter @@ -638,10 +634,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A07" Full Scan - 3040 - {query_map[3040][0]} - {query_map[3040][1]} + 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) @@ -650,10 +645,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A08" Full Scan - 3050 - {query_map[3050][0]} - {query_map[3050][1]} + 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 @@ -663,10 +657,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A09" Full Scan - 3060 - {query_map[3060][0]} - {query_map[3060][1]} + 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) @@ -675,10 +668,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A10" Full Scan - 3070 - {query_map[3070][0]} - {query_map[3070][1]} + 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 @@ -688,10 +680,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A11" Full Scan - 4000 - {query_map[4000][0]} - {query_map[4000][1]} + 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) @@ -700,10 +691,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A12" Full Scan - 4010 - {query_map[4010][0]} - {query_map[4010][1]} + 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 @@ -711,10 +701,13 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A13" Full Scan - 4020 - {query_map[4020][0]} - {query_map[4020][1]} + 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) @@ -723,10 +716,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A14" Full Scan - 4030 - {query_map[4030][0]} - {query_map[4030][1]} + 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 @@ -734,10 +726,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A15" Full Scan - 4040 - {query_map[4040][0]} - {query_map[4040][1]} + 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) @@ -746,10 +737,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A16" Full Scan - 4050 - {query_map[4050][0]} - {query_map[4050][1]} + 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) @@ -758,10 +748,9 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A17" Full Scan - 4060 - {query_map[4060][0]} - {query_map[4060][1]} + 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 @@ -769,10 +758,20 @@ Select Expression ....-> Filter (preliminary) ........-> Table "TEST" as "A18" Full Scan - 4070 - {query_map[4070][0]} - {query_map[4070][1]} + 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) @@ -789,73 +788,66 @@ ............-> Table "TEST" as "R A19" Full Scan ........-> Filter ............-> Table "TEST" as "R I" Full Scan - 5000 - {query_map[5000][0]} - {query_map[5000][1]} + 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 - {query_map[6000][0]} - {query_map[6000][1]} + 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 - {query_map[6010][0]} - {query_map[6010][1]} + 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 - {query_map[7000][0]} - {query_map[7000][1]} + 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 - {query_map[7010][0]} - {query_map[7010][1]} + 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 - {query_map[7020][0]} - {query_map[7020][1]} + 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 - {query_map[7030][0]} - {query_map[7030][1]} + 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 - {query_map[7040][0]} - {query_map[7040][1]} + 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 - {query_map[7050][0]} - {query_map[7050][1]} + 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 From 982fa842ef096ce207acbbb39e3a5abe94098896 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 16 Jan 2025 23:23:22 +0300 Subject: [PATCH 0321/1064] Added/Updated tests\bugs\gh_8185_test.py: Increased in version for FB 5.x --- tests/bugs/gh_8185_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8185_test.py b/tests/bugs/gh_8185_test.py index 68cad08d..6c73d2dc 100644 --- a/tests/bugs/gh_8185_test.py +++ b/tests/bugs/gh_8185_test.py @@ -48,7 +48,7 @@ db = db_factory(init = init_sql) act = python_act('db') -@pytest.mark.version('>=5.0.0') +@pytest.mark.version('>=5.0.1') def test_1(act: Action, capsys): srv_cfg = driver_config.register_server(name = 'test_srv_gh_8185', config = '') From 07c81fa5aa4e2123fedd85a11300c51f52a440df Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 17 Jan 2025 00:02:38 +0300 Subject: [PATCH 0322/1064] Added/Updated tests\bugs\gh_8386_test.py: Checked on 5.0.2.1592 -- all fine. WAITING FOR FRONT-PORT FIX INTO FB 6.X. --- tests/bugs/gh_8386_test.py | 119 +++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 tests/bugs/gh_8386_test.py diff --git a/tests/bugs/gh_8386_test.py b/tests/bugs/gh_8386_test.py new file mode 100644 index 00000000..65417da0 --- /dev/null +++ b/tests/bugs/gh_8386_test.py @@ -0,0 +1,119 @@ +#coding:utf-8 + +""" +ID: issue-8386 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8386 +TITLE: Crash when creating index on table that uses UDR and ParallelWorkers > 1 +DESCRIPTION: +NOTES: + [17.01.2025] pzotov + Currenty fix presents only in 5.x (commit 4ddbb69). Because of that, 6.x not checked (but it is also affected). + + Confirmed bug on 5.0.2.1589, got: "SQLSTATE = 08006 / Error reading data from the connection". + Checked on 5.0.2.1592 -- all fine. + WAITING FOR FRONT-PORT FIX INTO FB 6.X. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail on; + set list on; + create exception exc_parallel_workers_required q'[Config parameter ParallelWorkers = @1 must be set to 2 or greater.]'; + create exception exc_udr_func_seems_not_working q'[UDR function 'sum_args' either not defined or is invalid]'; + create exception exc_not_enough_data_for_test q'[At least 2 PP must be allocated for data of 'TEST' table. Currently only @1 PP are used.]'; + + -- create UDR + create function sum_args ( + n1 integer, + n2 integer, + n3 integer + ) returns integer + external name 'udrcpp_example!sum_args' + engine udr + ; + + set term ^; + execute block as + declare n int; + begin + select rdb$config_value from rdb$config where rdb$config_name = 'ParallelWorkers' into n; + if (n is null or n <= 1) then + exception exc_parallel_workers_required using (n); + -------------------------------------------- + select sum_args(1, 2, 3) from rdb$database into n; + if (n is distinct from 6) then + exception exc_udr_func_seems_not_working; + + end + ^ + set term ;^ + commit; + + -- create table with dependency on UDR + create table test ( + f1 int, + f2 int, + f3 int, + f_sum computed by (sum_args(f1, f2, f3)) + ); + + -- fill it with some data + insert into test values (1, 1, 1); + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + insert into test select f1, f2, f3 from test; + commit; + + set term ^; + execute block as + declare n int; + begin + -- make sure there are at least 2 pointer pages + select count(*) from rdb$pages p join rdb$relations r on p.rdb$relation_id = r.rdb$relation_id + where r.rdb$relation_name = upper('test') and p.rdb$page_type = 4 + into n; + if (n < 2) then + exception exc_not_enough_data_for_test using (n); + + end + ^ + set term ;^ + commit; + + -- create index + create index test_idx_f1 on test(f1); + + -- THIS MUST BE DISPLAYED. CRASH WAS HERE BEFORE FIX: + select 'Completed' as msg from rdb$database; +""" + +act = isql_act('db', test_script, substitutions = [('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0.2,<6') +def test_1(act: Action): + if act.vars['server-arch'] != 'SuperServer': + pytest.skip("Only SuperServer affected") + + act.expected_stdout = 'MSG Completed' + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From d847fa7cf6d32ea3cca4ade5fefd2162eeb8bed1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 17 Jan 2025 13:35:45 +0300 Subject: [PATCH 0323/1064] Added/Updated tests\bugs\gh_8386_test.py: DISABLED check for ServerMode, requested by dimitr --- tests/bugs/gh_8386_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8386_test.py b/tests/bugs/gh_8386_test.py index 65417da0..88ee047e 100644 --- a/tests/bugs/gh_8386_test.py +++ b/tests/bugs/gh_8386_test.py @@ -110,8 +110,10 @@ @pytest.mark.version('>=5.0.2,<6') def test_1(act: Action): - if act.vars['server-arch'] != 'SuperServer': - pytest.skip("Only SuperServer affected") + + # DISABLED 17.01.2025 13:35, requested by dimitr: + #if act.vars['server-arch'] != 'SuperServer': + # pytest.skip("Only SuperServer affected") act.expected_stdout = 'MSG Completed' act.execute(combine_output = True) From 213f3a472fc58691cc435dfab3e19a88ce2ec747 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 13:12:21 +0300 Subject: [PATCH 0324/1064] Added/Updated tests\bugs\gh_7304_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection after pytest finishes. --- tests/bugs/gh_7304_test.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_7304_test.py b/tests/bugs/gh_7304_test.py index 0c1a3c2d..89a35e97 100644 --- a/tests/bugs/gh_7304_test.py +++ b/tests/bugs/gh_7304_test.py @@ -32,8 +32,24 @@ FBTEST: bugs.core_2668 NOTES: [07.11.2024] pzotov - Confirmed absense of lines marked as '" in the trace log for snapshot 5.0.0.731 (15.09.2022). Checked on 5.0.0.733 (16.09.2022); 5.0.2.1553, 6.0.0.515 + + [18.01.2025] pzotov + ### CRITICAL ISSUE ### PROBABLY MUST BE APPLIED TO ALL TESTS WITH SIMILAR BEHAVOUR ### + + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises. + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, letter 26.10.24 17:42 + (subject: "oddities when use instances of selective statements"): + * line 'cur1.execute(ps1)' creates a new cursor but looses reference on it; + * but this cursor is linked with instance of ps1 which *has* reference on that cursor; + * call 'ps1.free()' delete this anonimous cursor but Python runtime + (or - maybe - code that makes connection cleanup) does not know about it + and tries to delete this anon cursor AGAIN when code finishes 'with' block. + This attempt causes AV. """ import time @@ -159,10 +175,15 @@ def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys): i = 0 da = dt.now() while True: - cur_watcher.execute(ps) + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute(ps) in order to close it + # *explicitly* otherwise AV can occur when Python collects garbage. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur_watcher.execute(ps) mon_result = -1 for r in cur_watcher: mon_result = r[0] + rs.close() # <<< EXPLICIT CLOSE RESULT OF CURSOR. tx_watcher.commit() db = dt.now() From 43524fadeafa0e0f14de286f47d6527ebb34e8fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 14:26:04 +0300 Subject: [PATCH 0325/1064] Added/Updated tests\bugs\core_0214_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_0214_test.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0214_test.py b/tests/bugs/core_0214_test.py index 01a34cbc..ef90073d 100644 --- a/tests/bugs/core_0214_test.py +++ b/tests/bugs/core_0214_test.py @@ -36,6 +36,13 @@ [03.12.2024] pzotov Made MAX_RATIO different for Windows vs Linux. Increased its value on Linux: in some cases it can be more than 2.33 + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import os import psutil @@ -218,9 +225,17 @@ def test_1(act: Action, capsys): psc = ps1 if c == cur1 else ps2 for i in range(0, N_MEASURES): fb_info_init = psutil.Process(fb_pid).cpu_times() + + # ::: NB ::: 'psc' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 rs = c.execute(psc) c.fetchall() - rs.close() + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + fb_info_curr = psutil.Process(fb_pid).cpu_times() cpu_usage_values.append( max(fb_info_curr.user - fb_info_init.user, 0.000001) ) From a8acc181686078da1405e9cd78a29695562de890 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 14:34:14 +0300 Subject: [PATCH 0326/1064] Added/Updated tests\bugs\gh_8252_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8252_test.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8252_test.py b/tests/bugs/gh_8252_test.py index 2fa5afbf..04cfd517 100644 --- a/tests/bugs/gh_8252_test.py +++ b/tests/bugs/gh_8252_test.py @@ -12,6 +12,13 @@ 2. Custom driver config object is created here for using 'SubQueryConversion = true'. 3. Additional test was made for this issue: tests/functional/tabloid/test_aae2ae32.py + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Confirmed bug on 5.0.2.1497. Checked on 5.0.2.1499-5fa4ae6. """ @@ -65,11 +72,23 @@ def test_1(act: Action, capsys): print(r[0],r[1]) ps = cur.prepare(test_sql) + # Show explained plan: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - for r in cur.execute(ps): + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: print(r[0]) - con.rollback() + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + ps.free() + + con.rollback() act.expected_stdout = """ SubQueryConversion true From eb99deb2ee2089a5582ea68260813255d7ef4982 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 14:46:39 +0300 Subject: [PATCH 0327/1064] Added/Updated tests\functional\tabloid\test_aae2ae32.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/functional/tabloid/test_aae2ae32.py | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/functional/tabloid/test_aae2ae32.py b/tests/functional/tabloid/test_aae2ae32.py index 1fed532d..afde4a68 100644 --- a/tests/functional/tabloid/test_aae2ae32.py +++ b/tests/functional/tabloid/test_aae2ae32.py @@ -25,6 +25,13 @@ Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 4. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Checked on 5.0.2.1516-92316F0 -- all ok: two hash joins instead of subquery. Thanks to dimitr for the advice on implementing the test. """ @@ -33,6 +40,7 @@ from firebird.qa import * from firebird.driver import driver_config, connect, DatabaseError + init_script = """ create table test1(id int not null); create table test2(id int not null, pid int not null); @@ -90,6 +98,7 @@ def test_1(act: Action, capsys): """ with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + ps, rs = None, None try: cur = con.cursor() cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") @@ -101,12 +110,23 @@ def test_1(act: Action, capsys): # Print explained plan with padding eash line by dots in order to see indentations: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - # Print data: - for r in cur.execute(ps): + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: print(r[0]) except DatabaseError as e: print(e.__str__()) print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() act.expected_stdout = f""" SubQueryConversion true From df454c615b3147906c1be14e76014341e91043a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 14:49:03 +0300 Subject: [PATCH 0328/1064] Added/Updated tests\bugs\gh_8233_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8233_test.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8233_test.py b/tests/bugs/gh_8233_test.py index 31ca0735..aff0d84a 100644 --- a/tests/bugs/gh_8233_test.py +++ b/tests/bugs/gh_8233_test.py @@ -13,6 +13,13 @@ Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 3. Table 't1' must have more than one row for bug reproducing. Query must be enclosed in execute block. 4. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). Checked on 5.0.2.1487-6934878 -- all ok. Thanks to dimitr for the advice on implementing the test. @@ -71,6 +78,7 @@ def test_1(act: Action, capsys): """ with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + ps, rs = None, None try: cur = con.cursor() cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") @@ -82,12 +90,23 @@ def test_1(act: Action, capsys): # Print explained plan with padding eash line by dots in order to see indentations: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - # Print data: - for r in cur.execute(ps): + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: print(r[0]) except DatabaseError as e: print(e.__str__()) print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() act.expected_stdout = f""" SubQueryConversion true From b480a3fe438942de214a2fce8946bb0615e10b4b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 14:58:29 +0300 Subject: [PATCH 0329/1064] Added/Updated tests\bugs\gh_8115_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8115_test.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_8115_test.py b/tests/bugs/gh_8115_test.py index 99b68e96..46bfd252 100644 --- a/tests/bugs/gh_8115_test.py +++ b/tests/bugs/gh_8115_test.py @@ -14,6 +14,13 @@ https://github.com/FirebirdSQL/firebird/commit/bbd35ab07c129e9735f081fcd29172a8187aa8ab Avoid reading/hashing the inner stream(s) if the leader stream is empty + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Checked on 6.0.0.457, 5.0.2.1499 """ import zipfile @@ -57,17 +64,29 @@ def test_1(act: Action, tmp_fbk: Path, capsys): 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')]) ) - + ps, rs = None, None try: - cur.execute(ps) - for r in cur: + ps = cur.prepare(test_sql) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: for p in r: print(p) except DatabaseError as e: print(e.__str__()) print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() expected_stdout_5x = """ Select Expression From 7a4b162bf8189c27d736a3937be438365d20804a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:02:29 +0300 Subject: [PATCH 0330/1064] Added/Updated tests\bugs\gh_8225_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8225_test.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_8225_test.py b/tests/bugs/gh_8225_test.py index 47eeeab7..4388518a 100644 --- a/tests/bugs/gh_8225_test.py +++ b/tests/bugs/gh_8225_test.py @@ -10,13 +10,20 @@ Parameter 'SubQueryConversion' currently presents only in FB 5.x and _NOT_ in FB 6.x. Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Confirmed bug on 5.0.2.1479-adfe97a. Checked on 5.0.2.1482-604555f. """ import pytest from firebird.qa import * -from firebird.driver import driver_config, connect +from firebird.driver import driver_config, connect, DatabaseError init_script = """ create domain dm_emp_id smallint; @@ -91,10 +98,30 @@ def test_1(act: Action, capsys): for r in cur: print(r[0],r[1]) - ps = cur.prepare(test_sql) - print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - for r in cur.execute(ps): - print(r[0],r[1]) + ps, rs = None, None + try: + ps = cur.prepare(test_sql) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + print(r[0],r[1]) + + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + con.rollback() act.expected_stdout = f""" From 4606cf91265b85f1253ef7d0d6950063a82e1945 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:04:36 +0300 Subject: [PATCH 0331/1064] Added/Updated tests\bugs\gh_8223_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8223_test.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8223_test.py b/tests/bugs/gh_8223_test.py index d5017dff..447baa1b 100644 --- a/tests/bugs/gh_8223_test.py +++ b/tests/bugs/gh_8223_test.py @@ -14,6 +14,13 @@ Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 3. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Checked on 5.0.2.1483-0bf2de0 -- all ok. Thanks to dimitr for the advice on implementing the test. """ @@ -80,6 +87,7 @@ def test_1(act: Action, capsys): """ with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + ps, rs = None, None try: cur = con.cursor() cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") @@ -91,12 +99,24 @@ def test_1(act: Action, capsys): # Print explained plan with padding eash line by dots in order to see indentations: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - # Print data: - for r in cur.execute(ps): + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: print(r[0], r[1], r[2]) except DatabaseError as e: print(e.__str__()) print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + act.expected_stdout = f""" SubQueryConversion true From 1301cd17ffac9666edfb94425aadd3864ba57257 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:07:04 +0300 Subject: [PATCH 0332/1064] Added/Updated tests\bugs\gh_8231_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_8231_test.py | 40 ++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_8231_test.py b/tests/bugs/gh_8231_test.py index 3ac420cc..a91a43aa 100644 --- a/tests/bugs/gh_8231_test.py +++ b/tests/bugs/gh_8231_test.py @@ -13,12 +13,19 @@ request size limit exceeded Checked on 5.0.2.1485-274af35 -- all ok. + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Thanks to dimitr for the advice on implementing the test. """ import pytest from firebird.qa import * -from firebird.driver import driver_config, connect +from firebird.driver import driver_config, connect, DatabaseError init_script = """ create table t1(fld varchar(10) character set win1252); @@ -66,14 +73,31 @@ def test_1(act: Action, capsys): for r in cur: print(r[0],r[1]) - ps = cur.prepare(test_sql) + ps, rs = None, None + try: + ps = cur.prepare(test_sql) + + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + print(r[0]) + except: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() - # Print explained plan with padding eash line by dots in order to see indentations: - print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - - # Print data: - for r in cur.execute(ps): - print(r[0]) con.rollback() act.expected_stdout = f""" From 0f6cc4a53bca3082c312f9ca65865086ff5c38a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:22:53 +0300 Subject: [PATCH 0333/1064] Added/Updated tests\bugs\gh_7257_misc_datatypes_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_7257_misc_datatypes_test.py | 42 ++++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_7257_misc_datatypes_test.py b/tests/bugs/gh_7257_misc_datatypes_test.py index 8fcaa582..112dbce2 100644 --- a/tests/bugs/gh_7257_misc_datatypes_test.py +++ b/tests/bugs/gh_7257_misc_datatypes_test.py @@ -7,11 +7,19 @@ DESCRIPTION: Additional test to check misc datatypes in partial indices. NOTES: + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Checked on 6.0.0.409, 5.0.1.1469 """ import pytest from firebird.qa import * +from firebird.driver import DatabaseError from decimal import Decimal db = db_factory() @@ -78,16 +86,32 @@ def run_ddl_dml(act, capsys, dtype, v_chk, v_max, use_rand = True): con.commit() for x in [p for p in dml.split('^') if p.strip()]: - ps = cur.prepare(x) - for s in ps.detailed_plan.split('\n'): - print( replace_leading(s) ) + ps, rs = None, None + try: + ps = cur.prepare(x) + for s in ps.detailed_plan.split('\n'): + print( replace_leading(s) ) - cur.execute(ps) - cur_cols = cur.description - for r in cur: - for i in range(0,len(cur_cols)): - print( cur_cols[i][0], ':', r[i] ) - con.commit() + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + cur_cols = cur.description + for r in rs: + for i in range(0,len(cur_cols)): + print( cur_cols[i][0], ':', r[i] ) + con.commit() + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() act.expected_stdout = f""" Select Expression From 96d4f2b8a594edab65fb4b86b5e4ce36f65a74e4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:23:24 +0300 Subject: [PATCH 0334/1064] Added/Updated tests\bugs\gh_8231_test.py: added forgotten 'DatabaseError as e' --- tests/bugs/gh_8231_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8231_test.py b/tests/bugs/gh_8231_test.py index a91a43aa..30353afb 100644 --- a/tests/bugs/gh_8231_test.py +++ b/tests/bugs/gh_8231_test.py @@ -89,7 +89,7 @@ def test_1(act: Action, capsys): rs = cur.execute(ps) for r in rs: print(r[0]) - except: + except DatabaseError as e: print(e.__str__()) print(e.gds_codes) finally: From 0f6e521c9551ae3bc34e661008df15688c8cce28 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:28:06 +0300 Subject: [PATCH 0335/1064] Added/Updated tests\bugs\gh_7917_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_7917_test.py | 39 +++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_7917_test.py b/tests/bugs/gh_7917_test.py index 7413ab15..aacaafc2 100644 --- a/tests/bugs/gh_7917_test.py +++ b/tests/bugs/gh_7917_test.py @@ -36,7 +36,6 @@ 3. In case of regression caused by that bug, we have to be ready that FB will hang on this test! Great thanks to Alex for suggestions (discussion started 13.12.2023 13:18). - Confirmed bug on 6.0.0.173. [30.01.2024] pzotov @@ -49,6 +48,14 @@ [01.02.2024] pzotov Added check for testing vanilla FB (temporary, until appropriate commits not merged with HQbird fork). + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + """ import os import time @@ -134,10 +141,10 @@ def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): d1 = py_dt.timedelta(0) with act.db.connect() as con: cur = con.cursor() - ps = cur.prepare('select mon$crypt_state from mon$database') - - t1=py_dt.datetime.now() + ps, rs = None, None try: + ps = cur.prepare('select mon$crypt_state from mon$database') + t1=py_dt.datetime.now() d1 = t1-t1 con.execute_immediate(alter_db_sttm) con.commit() @@ -147,11 +154,18 @@ def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: break - ###################################################### - ### C H E C K M O N $ C R Y P T _ S T A T E ### - ###################################################### - cur.execute(ps) - current_crypt_state = cur.fetchone()[0] + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + ###################################################### + ### C H E C K M O N $ C R Y P T _ S T A T E ### + ###################################################### + current_crypt_state = r[0] con.commit() if current_crypt_state == REQUIRED_CRYPT_STATE: e_thread_finished = True @@ -160,6 +174,13 @@ def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): time.sleep(0.5) except DatabaseError as e: print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + assert e_thread_finished, f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms; current_crypt_state={current_crypt_state}' From 3e94d0843ddb9cc145f63f20c65639df00192edb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 15:56:57 +0300 Subject: [PATCH 0336/1064] Added/Updated tests\bugs\gh_7863_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_7863_test.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_7863_test.py b/tests/bugs/gh_7863_test.py index 16e714db..fb328f3e 100644 --- a/tests/bugs/gh_7863_test.py +++ b/tests/bugs/gh_7863_test.py @@ -6,6 +6,13 @@ TITLE: Non-correlated sub-query is evaluated multiple times if it is based on a VIEW rathe than on appropriate derived table. DESCRIPTION: NOTES: + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Confirmed bug on 6.0.0.222 Checked on 6.0.0.223, 5.0.1.1322. """ @@ -58,12 +65,21 @@ def test_1(act: Action, capsys): result_map = {} for qry_txt in q_map.keys(): - with cur.prepare(qry_txt) as ps: + ps, rs = None, None + try: + ps = cur.prepare(qry_txt) q_map[qry_txt] = ps.detailed_plan for tab_nm,tab_id in t_map.items(): tabstat1 = [ p for p in con.info.get_table_access_stats() if p.table_id == tab_id ] - cur.execute(qry_txt) - for r in cur: + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: pass tabstat2 = [ p for p in con.info.get_table_access_stats() if p.table_id == tab_id ] @@ -77,6 +93,14 @@ def test_1(act: Action, capsys): seq -= (tabstat1[0].sequential if tabstat1[0].sequential else 0) idx -= (tabstat1[0].indexed if tabstat1[0].indexed else 0) result_map[qry_txt, tab_nm] = (seq, idx) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() for k,v in result_map.items(): print(k[0]) # query From d400394ff7991524d7694f107f953e0b1a555b26 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:03:50 +0300 Subject: [PATCH 0337/1064] Added/Updated tests\bugs\gh_7863_test.py: added forgotten import --- tests/bugs/gh_7863_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_7863_test.py b/tests/bugs/gh_7863_test.py index fb328f3e..70555e01 100644 --- a/tests/bugs/gh_7863_test.py +++ b/tests/bugs/gh_7863_test.py @@ -17,9 +17,11 @@ Checked on 6.0.0.223, 5.0.1.1322. """ -import pytest from pathlib import Path + +import pytest from firebird.qa import * +from firebird.driver import DatabaseError init_sql = """ create view v_test_nr as select 1 i from rdb$fields rows 50; From 76ed0fa4b94330b33dd25e879932a2e58ea03fab Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:04:07 +0300 Subject: [PATCH 0338/1064] Added/Updated tests\bugs\gh_7804_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_7804_test.py | 276 ++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 123 deletions(-) diff --git a/tests/bugs/gh_7804_test.py b/tests/bugs/gh_7804_test.py index 6e9d767b..7f7688b2 100644 --- a/tests/bugs/gh_7804_test.py +++ b/tests/bugs/gh_7804_test.py @@ -29,9 +29,19 @@ More realistic cardinality adjustments for unmatchable booleans, this should also fix #7904: FB5 bad plan for query Output for FB 6.x will be changed later (letter from dimitr, 16.12.2023 10:32) + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ + import pytest + from firebird.qa import * +from firebird.driver import DatabaseError init_script = """ recreate table test(x smallint); @@ -51,7 +61,7 @@ #---------------------------------------------------------- -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped @@ -82,10 +92,19 @@ def test_1(act: Action, capsys): result_map = {} for x in q_list: - with cur.prepare(x) as ps: + ps, rs = None, None + try: + ps = cur.prepare(x) tabstat1 = [ p for p in con.info.get_table_access_stats() if p.table_id == test_rel_id ] - cur.execute(x) - for r in cur: + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: pass tabstat2 = [ p for p in con.info.get_table_access_stats() if p.table_id == test_rel_id ] @@ -101,10 +120,21 @@ def test_1(act: Action, capsys): tabstat2[0].sequential if tabstat2[0].sequential else 0 ,tabstat2[0].indexed if tabstat2[0].indexed else 0 ) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() for k,v in result_map.items(): print('Query:', k[0]) - print( '\n'.join([replace_leading(s) for s in k[1].split('\n')]) ) # explained plan, with preserving indents by replacing leading spaces with '#' + + # Show explained plan, with preserving indents by replacing leading spaces with '.': + print( '\n'.join([replace_leading(s) for s in k[1].split('\n')]) ) + print('NR:', v[0]) print('IR:', v[1]) print('') @@ -114,109 +144,109 @@ def test_1(act: Action, capsys): expected_fb5x = f""" Query: {q_list[0]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 1000 Query: select * from test where x = 3 or x = 2 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 2000 Query: select * from test where x = 2 or x = 3 or x = 1 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap - ########################-> Index "TEST_X_ASC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_ASC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "TEST_X_ASC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 3000 Query: select * from test where x = 2 or x is null or x = 3 or x = 1 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap Or - ########################-> Bitmap - ############################-> Index "TEST_X_ASC" Range Scan (full match) - ########################-> Bitmap - ############################-> Index "TEST_X_ASC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_ASC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap Or + ........................-> Bitmap + ............................-> Index "TEST_X_ASC" Range Scan (full match) + ........................-> Bitmap + ............................-> Index "TEST_X_ASC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 4000 Query: select * from test where x = 5 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 1000 Query: select * from test where x = 6 or x = 5 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 2000 Query: select * from test where x = 5 or x = 4 or x = 6 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap - ########################-> Index "TEST_X_DEC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_DEC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "TEST_X_DEC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 3000 Query: select * from test where x = 6 or x is null or x = 4 or x = 5 Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap Or - ########################-> Bitmap - ############################-> Index "TEST_X_DEC" Range Scan (full match) - ########################-> Bitmap - ############################-> Index "TEST_X_DEC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_DEC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap Or + ........................-> Bitmap + ............................-> Index "TEST_X_DEC" Range Scan (full match) + ........................-> Bitmap + ............................-> Index "TEST_X_DEC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 4000 """ @@ -225,91 +255,91 @@ def test_1(act: Action, capsys): expected_fb6x = f""" Query: {q_list[0]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 1000 Query: {q_list[1]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 2000 Query: {q_list[2]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap - ########################-> Index "TEST_X_ASC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_ASC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_ASC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "TEST_X_ASC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) NR: 0 IR: 3000 Query: {q_list[3]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_ASC" Full Scan + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Full Scan NR: 0 IR: 4000 Query: {q_list[4]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 1000 Query: {q_list[5]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 2000 Query: {q_list[6]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap Or - ################-> Bitmap Or - ####################-> Bitmap - ########################-> Index "TEST_X_DEC" Range Scan (full match) - ####################-> Bitmap - ########################-> Index "TEST_X_DEC" Range Scan (full match) - ################-> Bitmap - ####################-> Index "TEST_X_DEC" Range Scan (full match) + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "TEST_X_DEC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_X_DEC" Range Scan (full match) NR: 0 IR: 3000 Query: {q_list[7]} Select Expression - ####-> Filter - ########-> Table "TEST" Access By ID - ############-> Bitmap - ################-> Index "TEST_X_DEC" Full Scan + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DEC" Full Scan NR: 0 IR: 4000 """ From 7740052e00420f98e03374c678645ff40cc33bde Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:08:16 +0300 Subject: [PATCH 0339/1064] Added/Updated tests\bugs\gh_7388_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_7388_test.py | 40 ++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/tests/bugs/gh_7388_test.py b/tests/bugs/gh_7388_test.py index 7fa40747..89735d7e 100644 --- a/tests/bugs/gh_7388_test.py +++ b/tests/bugs/gh_7388_test.py @@ -13,11 +13,20 @@ [20.01.2024] pzotov Confirmed problem on 5.0.0.871. Checked on 6.0.0.218, 5.0.1.1318. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ -import pytest from pathlib import Path + +import pytest from firebird.qa import * +from firebird.driver import DatabaseError init_sql = """ create view v1 @@ -37,7 +46,7 @@ #---------------------------------------------------------- -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped @@ -78,12 +87,21 @@ def test_1(act: Action, capsys): result_map = {} for qry_txt in q_map.keys(): - with cur.prepare(qry_txt) as ps: + ps, rs = None, None + try: + ps = cur.prepare(qry_txt) q_map[qry_txt] = ps.detailed_plan for tab_nm,tab_id in t_map.items(): tabstat1 = [ p for p in con.info.get_table_access_stats() if p.table_id == tab_id ] - cur.execute(qry_txt) - for r in cur: + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: pass tabstat2 = [ p for p in con.info.get_table_access_stats() if p.table_id == tab_id ] @@ -98,6 +116,15 @@ def test_1(act: Action, capsys): idx -= (tabstat1[0].indexed if tabstat1[0].indexed else 0) result_map[qry_txt, tab_nm] = (seq, idx) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + ''' print('q_map.items():') for k,v in q_map.items(): @@ -133,7 +160,8 @@ def test_1(act: Action, capsys): print(qry_txt) print('-' * 22) print('Plan:') - print( '\n'.join([replace_leading(s) for s in q_map[qry_txt].split('\n')]) ) # explained plan, with preserving indents by replacing leading spaces with '#' + # Show explained plan, with preserving indents by replacing leading spaces with '.': + print( '\n'.join([replace_leading(s) for s in q_map[qry_txt].split('\n')]) ) print('') else: print(SUCCESS_MSG) From 1fc6791847ce1649660977335e7c4ba5c887867e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:16:50 +0300 Subject: [PATCH 0340/1064] Added/Updated tests\bugs\gh_7200_test.py: added comments --- tests/bugs/gh_7200_test.py | 77 ++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/tests/bugs/gh_7200_test.py b/tests/bugs/gh_7200_test.py index f0de731c..e119ec36 100644 --- a/tests/bugs/gh_7200_test.py +++ b/tests/bugs/gh_7200_test.py @@ -37,6 +37,13 @@ Increased number of inserted rows (from 100'000 to 200'000) and indexed column width (from 700 to 800). Otherwise test could fail because encryption thread completes too fast (encountered under Linux). Loop that checks for appearance of encryption state = 3 must have delay much less than one second (changed it from 1 to 0.1). + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import datetime as py_dt @@ -128,34 +135,48 @@ def test_1(act: Action, act_tmp: Action, tmp_sql: Path, tmp_log: Path, capsys): encryption_started = False with act_tmp.db.connect() as con_watcher: - - custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) - tx_watcher = con_watcher.transaction_manager(custom_tpb) - cur_watcher = tx_watcher.cursor() - - # 0 = non-encrypted; 1 = encrypted; 2 = is DEcrypting; 3 - is Encrypting - ps = cur_watcher.prepare('select mon$crypt_state from mon$database') - - i = 0 - da = dt.now() - while True: - cur_watcher.execute(ps) - for r in cur_watcher: - db_crypt_state = r[0] - - tx_watcher.commit() - db = dt.now() - diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 - if db_crypt_state == IS_ENCRYPTING_STATE: - encryption_started = True - cur_watcher.call_procedure('sp_debug', ('encryption_started',)) - break - elif diff_ms > MAX_WAIT_FOR_ENCRYPTION_START_MS: - break - - time.sleep(0.1) - - ps.free() + + ps, rs = None, None + try: + custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) + tx_watcher = con_watcher.transaction_manager(custom_tpb) + cur_watcher = tx_watcher.cursor() + + # 0 = non-encrypted; 1 = encrypted; 2 = is DEcrypting; 3 - is Encrypting + ps = cur_watcher.prepare('select mon$crypt_state from mon$database') + + i = 0 + da = dt.now() + while True: + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur_watcher.execute(ps) + for r in rs: + db_crypt_state = r[0] + + tx_watcher.commit() + db = dt.now() + diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 + if db_crypt_state == IS_ENCRYPTING_STATE: + encryption_started = True + cur_watcher.call_procedure('sp_debug', ('encryption_started',)) + break + elif diff_ms > MAX_WAIT_FOR_ENCRYPTION_START_MS: + break + time.sleep(0.1) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() assert encryption_started, f'Could not find start of encryption process for {MAX_WAIT_FOR_ENCRYPTION_START_MS} ms.' From 902f10a4fad9778b616a9c720cec8c4dc49335d9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:18:15 +0300 Subject: [PATCH 0341/1064] Added/Updated tests\bugs\gh_6947_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_6947_test.py | 84 +++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/tests/bugs/gh_6947_test.py b/tests/bugs/gh_6947_test.py index de7e70ae..34d55274 100644 --- a/tests/bugs/gh_6947_test.py +++ b/tests/bugs/gh_6947_test.py @@ -28,6 +28,13 @@ [11.03.2023] pzotov Marked as SKIPPED because covered by core_6048_test. Probably will be deleted soon. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import os import datetime as py_dt @@ -118,38 +125,57 @@ def test_1(act: Action, capsys): cur = con.cursor() cu2 = con.cursor() - ps = cur.prepare('select mon$crypt_page from mon$database') - - while encryption_started: - t2=py_dt.datetime.now() - d1=t2-t1 - if d1.seconds*1000 + d1.microseconds//1000 > MAX_WAITING_ENCR_FINISH: - print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {MAX_WAITING_ENCR_FINISH} ms.') - break - - cur.execute(ps) - p = cur.fetchone()[0] - cu2.callproc('sp_tmp', [ p, ] ) - con.commit() - - if p > 0: - encrypted_pages_set.add(p) - if len(encrypted_pages_set) >= MIN_DISTINCT_ENCRYPTED_PAGES: - # We got enough data from mon$database to conclude that encryption is in PROGRESS. + ps, rs = None, None + try: + ps = cur.prepare('select mon$crypt_page from mon$database') + while encryption_started: + t2=py_dt.datetime.now() + d1=t2-t1 + if d1.seconds*1000 + d1.microseconds//1000 > MAX_WAITING_ENCR_FINISH: + print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {MAX_WAITING_ENCR_FINISH} ms.') break - # Possible output: - # Database not encrypted - # Database encrypted, crypt thread not complete - act.isql(switches=['-q'], input = 'show database;', combine_output = True) - if 'Database encrypted' in act.stdout: - if 'not complete' in act.stdout: - pass - else: - encryption_finished = True - break - act.reset() + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + p = r[0] + + cu2.callproc('sp_tmp', [ p, ] ) + con.commit() + + if p > 0: + encrypted_pages_set.add(p) + if len(encrypted_pages_set) >= MIN_DISTINCT_ENCRYPTED_PAGES: + # We got enough data from mon$database to conclude that encryption is in PROGRESS. + break + + # Possible output: + # Database not encrypted + # Database encrypted, crypt thread not complete + act.isql(switches=['-q'], input = 'show database;', combine_output = True) + if 'Database encrypted' in act.stdout: + if 'not complete' in act.stdout: + pass + else: + encryption_finished = True + break + act.reset() + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + if encryption_started: if len(encrypted_pages_set) >= MIN_DISTINCT_ENCRYPTED_PAGES: print(expected_stdout) From bdce1031597b9a197aa3ceb891db7f7c09a82105 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:22:27 +0300 Subject: [PATCH 0342/1064] Added/Updated tests\bugs\core_6458_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_6458_test.py | 118 +++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/tests/bugs/core_6458_test.py b/tests/bugs/core_6458_test.py index ca6c82c8..59e2eecc 100644 --- a/tests/bugs/core_6458_test.py +++ b/tests/bugs/core_6458_test.py @@ -5,35 +5,41 @@ ISSUE: 6691 TITLE: Regression: Cancel Query function no longer works DESCRIPTION: - We create .sql script with 'heavy query' that for sure will run more than several seconds. - Then we launch asynchronously ISQL to perform this query and wait until its PID and running - query will appear in the mon$ tables (we are looking for query that containing text 'HEAVY_TAG'). - - After this we send signal CTRL_C_EVENT for emulating interruption that is done by pressing Ctrl-C. - Then we wait for process finish (call wait() method) - this is necessary if ISQL will continue - without interruprion (i.e. if something will be broken again). - - When method wait() will return control back, we can obtain info about whether child process was - terminated or no (using method poll()). If yes (expected) then it must return 1. - - Finally, we check ISQL logs for STDOUT and STDERR. They must be as follows: - * STDOUT -- must be empty - * STDERR -- must contain (at least) two phrases: - 1. Statement failed, SQLSTATE = HY008 - 2. operation was cancelled - - ::: NB ::: - Windows only: subprocess.Popen() must have argument: creationflags = subprocess.CREATE_NEW_PROCESS_GROUP - Otherwise we can not send signal Ctrl_C_EVENT to the child process. - Linux: parameter 'creationflags' must be 0, signal.SIGINT is used instead of Ctrl_C_EVENT. - - See: https://docs.python.org/2.7/library/subprocess.html - - Confirmed bug on 4.0.0.2307: query could NOT be interrupted and we had to wait until it completed. - Checked on 4.0.0.2324 (SS/CS): works OK, query can be interrupted via sending Ctrl-C signal. - -JIRA: CORE-6458 + We create .sql script with 'heavy query' that for sure will run more than several seconds. + Then we launch asynchronously ISQL to perform this query and wait until its PID and running + query will appear in the mon$ tables (we are looking for query that containing text 'HEAVY_TAG'). + + After this we send signal CTRL_C_EVENT for emulating interruption that is done by pressing Ctrl-C. + Then we wait for process finish (call wait() method) - this is necessary if ISQL will continue + without interruprion (i.e. if something will be broken again). + + When method wait() will return control back, we can obtain info about whether child process was + terminated or no (using method poll()). If yes (expected) then it must return 1. + + Finally, we check ISQL logs for STDOUT and STDERR. They must be as follows: + * STDOUT -- must be empty + * STDERR -- must contain (at least) two phrases: + 1. Statement failed, SQLSTATE = HY008 + 2. operation was cancelled FBTEST: bugs.core_6458 +NOTES: + + ::: NB ::: + Windows only: subprocess.Popen() must have argument: creationflags = subprocess.CREATE_NEW_PROCESS_GROUP + Otherwise we can not send signal Ctrl_C_EVENT to the child process. + Linux: parameter 'creationflags' must be 0, signal.SIGINT is used instead of Ctrl_C_EVENT. + + See: https://docs.python.org/2.7/library/subprocess.html + + Confirmed bug on 4.0.0.2307: query could NOT be interrupted and we had to wait until it completed. + Checked on 4.0.0.2324 (SS/CS): works OK, query can be interrupted via sending Ctrl-C signal. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import re @@ -100,28 +106,44 @@ def test_1(act: Action, heavy_script: Path, heavy_stdout: Path, heavy_stderr: Pa tx_watcher = con_watcher.transaction_manager(custom_tpb) cur_watcher = tx_watcher.cursor() - ps = cur_watcher.prepare(chk_mon_sql) - - i = 0 - da = dt.now() - while True: - cur_watcher.execute(ps, (p_heavy_sql.pid, HEAVY_TAG,) ) - mon_result = -1 - for r in cur_watcher: - mon_result = r[0] - - tx_watcher.commit() - db = dt.now() - diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 - if mon_result == 1: - found_in_mon_tables = True - break - elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: - break + ps, rs = None, None + try: + ps = cur_watcher.prepare(chk_mon_sql) + + i = 0 + da = dt.now() + while True: + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur_watcher.execute(ps, (p_heavy_sql.pid, HEAVY_TAG,) ) + mon_result = -1 + for r in rs: + mon_result = r[0] + + tx_watcher.commit() + db = dt.now() + diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 + if mon_result == 1: + found_in_mon_tables = True + break + elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: + break + time.sleep(0.1) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() - time.sleep(0.1) - ps.free() assert found_in_mon_tables, f'Could not find attachment in mon$ tables for {MAX_WAIT_FOR_ISQL_PID_APPEARS_MS} ms.' From da0580b307a1772f5e7364e97a0426d553b16d6d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:26:13 +0300 Subject: [PATCH 0343/1064] Added/Updated tests\bugs\core_6048_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_6048_test.py | 93 +++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/tests/bugs/core_6048_test.py b/tests/bugs/core_6048_test.py index b83265e6..e0acd313 100644 --- a/tests/bugs/core_6048_test.py +++ b/tests/bugs/core_6048_test.py @@ -33,6 +33,13 @@ ::: NB-2 ::: Careful tuning required on each tesing box for this test. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import os @@ -125,39 +132,59 @@ def test_1(act: Action, capsys): print( e.__str__() ) cur2 = con2.cursor() - ps = cur2.prepare('select mon$crypt_page, mon$crypt_state from mon$database') - - # This will store different number of pages which are currently encrypted. - # When length of this set will exceed ENCRYPTING_PAGES_MIN_CNT then we break from loop: - # - encrypting_pages_set = set() - waiting_in_loop = -1 - while encryption_started: - t2=py_dt.datetime.now() - d1=t2-t1 - waiting_in_loop = d1.seconds*1000 + d1.microseconds//1000 - if waiting_in_loop > MAX_WAITING_ENCR_FINISH: - print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {MAX_WAITING_ENCR_FINISH} ms.') - break - - cur2.execute(ps) - crypt_page, crypt_state = cur2.fetchone() - con2.commit() - - # 0 = non crypted; - # 1 = has been encrypted; - # 2 = is DEcrypting; - # 3 = is Encrypting; - if crypt_state == RUNNING_ENCRYPTING_STATE: - encrypting_pages_set.add(crypt_page,) - - if crypt_state == COMPLETED_ENCRYPTION_STATE: - encryption_finished = True - break - elif len(encrypting_pages_set) > ENCRYPTING_PAGES_MIN_CNT: - break - else: - time.sleep(0.5) + ps, rs = None, None + + try: + ps = cur2.prepare('select mon$crypt_page, mon$crypt_state from mon$database') + + # This will store different number of pages which are currently encrypted. + # When length of this set will exceed ENCRYPTING_PAGES_MIN_CNT then we break from loop: + # + encrypting_pages_set = set() + waiting_in_loop = -1 + while encryption_started: + t2=py_dt.datetime.now() + d1=t2-t1 + waiting_in_loop = d1.seconds*1000 + d1.microseconds//1000 + if waiting_in_loop > MAX_WAITING_ENCR_FINISH: + print(f'TIMEOUT EXPIRATION: encryption took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {MAX_WAITING_ENCR_FINISH} ms.') + break + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur2.execute(ps) + for r in rs: + crypt_page, crypt_state = r[:2] + + con2.commit() + + # 0 = non crypted; + # 1 = has been encrypted; + # 2 = is DEcrypting; + # 3 = is Encrypting; + if crypt_state == RUNNING_ENCRYPTING_STATE: + encrypting_pages_set.add(crypt_page,) + + if crypt_state == COMPLETED_ENCRYPTION_STATE: + encryption_finished = True + break + elif len(encrypting_pages_set) > ENCRYPTING_PAGES_MIN_CNT: + break + else: + time.sleep(0.1) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() # --------------------------------------------------------- From 9ea5d26d92dc76f2530aa507f3a969111c282aa1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:31:16 +0300 Subject: [PATCH 0344/1064] Added/Updated tests\bugs\core_5646_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_5646_test.py | 212 +++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 96 deletions(-) diff --git a/tests/bugs/core_5646_test.py b/tests/bugs/core_5646_test.py index ccfd5b64..fba60da1 100644 --- a/tests/bugs/core_5646_test.py +++ b/tests/bugs/core_5646_test.py @@ -5,87 +5,92 @@ ISSUE: 5912 TITLE: Parse error when compiling a statement causes memory leak until attachment is disconnected DESCRIPTION: - Test uses DDL and query for well known Einstein task. - SQL query for solution of this task is quite complex and must consume some memory resources. - This query intentionally is made non-compilable, so actually it will not ever run. - We query mon$memory_usage before running this query and after it, with storing values mon$memory* fields in the dictionary. - We do runs and after this evaluate differences of comsumed memory for each run. - Build 4.0.0.483 (05-jan-2017) shows that: - * mon$memory_used increased for ~227 Kb each run; - * mon$memory_allocated increased for ~960Kb. - Build 4.0.0.840 (02-jan-2018) shows that mon$memory_used increased for 2Kb - but only at FIRST measure. - Since 2nd measure memory consumption did not increase (neither mon$memory_used nor mon$memory_allocated). - But mon$max_memory_used can slightly increase, only ONCE, at 3rd run, for about 1Kb. - - Test evaluates MEDIANS for differences of mon$memory* fields. - All these medians must be ZERO otherwise test is considered as failed. + Test uses DDL and query for well known Einstein task. + SQL query for solution of this task is quite complex and must consume some memory resources. + This query intentionally is made non-compilable, so actually it will not ever run. + We query mon$memory_usage before running this query and after it, with storing values mon$memory* fields in the dictionary. + We do runs and after this evaluate differences of comsumed memory for each run. + Build 4.0.0.483 (05-jan-2017) shows that: + * mon$memory_used increased for ~227 Kb each run; + * mon$memory_allocated increased for ~960Kb. + Build 4.0.0.840 (02-jan-2018) shows that mon$memory_used increased for 2Kb - but only at FIRST measure. + Since 2nd measure memory consumption did not increase (neither mon$memory_used nor mon$memory_allocated). + But mon$max_memory_used can slightly increase, only ONCE, at 3rd run, for about 1Kb. + + Test evaluates MEDIANS for differences of mon$memory* fields. + All these medians must be ZERO otherwise test is considered as failed. JIRA: CORE-5646 FBTEST: bugs.core_5646 NOTES: [27.11.2023] pzotov - commit to FB 4.x: 26-nov-2017 - https://github.com/FirebirdSQL/firebird/commit/5e1b5e172e95388f8f2f236b89295bb915aef397 - - commit to FB 3.x: 06-oct-2021 - https://github.com/FirebirdSQL/firebird/commit/ed585ab09fdad63551c48d1ce392c810b5cef4a8 - (since build 3.0.8.33519, date: 07-oct-2021) - - 4.0.0.483, 05-jan-2017 - ====================== - absolute values: - 1 ::: (2329392, 2818048, 2569880, 2818048) - 2 ::: (2565264, 4456448, 3380832, 4653056) - 3 ::: (2565264, 4456448, 3380832, 4653056) - 4 ::: (2798240, 5373952, 3614280, 5636096) - 5 ::: (2798240, 5373952, 3614280, 5636096) - 6 ::: (3031216, 6356992, 3846784, 6619136) - 7 ::: (3031216, 6356992, 3846784, 6619136) - 8 ::: (3264192, 7340032, 4079760, 7602176) - 9 ::: (3264192, 7340032, 4079760, 7602176) - 10 ::: (3497400, 8323072, 4312968, 8585216) - 11 ::: (3497400, 8323072, 4312968, 8585216) - 12 ::: (3730376, 9240576, 4545944, 9502720) - 13 ::: (3730376, 9240576, 4545944, 9502720) - 14 ::: (3963352, 10223616, 4778920, 10485760) - 15 ::: (3963352, 10223616, 4778920, 10485760) - 16 ::: (4196328, 11141120, 5011896, 11403264) - 17 ::: (4196328, 11141120, 5011896, 11403264) - 18 ::: (4429304, 12124160, 5244872, 12386304) - 19 ::: (4429304, 12124160, 5244872, 12386304) - 20 ::: (4662280, 13041664, 5477848, 13303808) - 21 ::: (4662280, 13041664, 5477848, 13303808) - 22 ::: (4895256, 14024704, 5710824, 14286848) - - differences: - 0 ::: [235872, 1638400, 810952, 1835008] - 1 ::: [232976, 917504, 233448, 983040] - 2 ::: [232976, 983040, 232504, 983040] - 3 ::: [232976, 983040, 232976, 983040] - 4 ::: [233208, 983040, 233208, 983040] - 5 ::: [232976, 917504, 232976, 917504] - 6 ::: [232976, 983040, 232976, 983040] - 7 ::: [232976, 917504, 232976, 917504] - 8 ::: [232976, 983040, 232976, 983040] - 9 ::: [232976, 917504, 232976, 917504] - 10 ::: [232976, 983040, 232976, 983040] - + commit to FB 4.x: 26-nov-2017 + https://github.com/FirebirdSQL/firebird/commit/5e1b5e172e95388f8f2f236b89295bb915aef397 + + commit to FB 3.x: 06-oct-2021 + https://github.com/FirebirdSQL/firebird/commit/ed585ab09fdad63551c48d1ce392c810b5cef4a8 + (since build 3.0.8.33519, date: 07-oct-2021) + + 4.0.0.483, 05-jan-2017 + ====================== + absolute values: + 1 ::: (2329392, 2818048, 2569880, 2818048) + 2 ::: (2565264, 4456448, 3380832, 4653056) + 3 ::: (2565264, 4456448, 3380832, 4653056) + 4 ::: (2798240, 5373952, 3614280, 5636096) + 5 ::: (2798240, 5373952, 3614280, 5636096) + 6 ::: (3031216, 6356992, 3846784, 6619136) + 7 ::: (3031216, 6356992, 3846784, 6619136) + 8 ::: (3264192, 7340032, 4079760, 7602176) + 9 ::: (3264192, 7340032, 4079760, 7602176) + 10 ::: (3497400, 8323072, 4312968, 8585216) + 11 ::: (3497400, 8323072, 4312968, 8585216) + 12 ::: (3730376, 9240576, 4545944, 9502720) + 13 ::: (3730376, 9240576, 4545944, 9502720) + 14 ::: (3963352, 10223616, 4778920, 10485760) + 15 ::: (3963352, 10223616, 4778920, 10485760) + 16 ::: (4196328, 11141120, 5011896, 11403264) + 17 ::: (4196328, 11141120, 5011896, 11403264) + 18 ::: (4429304, 12124160, 5244872, 12386304) + 19 ::: (4429304, 12124160, 5244872, 12386304) + 20 ::: (4662280, 13041664, 5477848, 13303808) + 21 ::: (4662280, 13041664, 5477848, 13303808) + 22 ::: (4895256, 14024704, 5710824, 14286848) + + differences: + 0 ::: [235872, 1638400, 810952, 1835008] + 1 ::: [232976, 917504, 233448, 983040] + 2 ::: [232976, 983040, 232504, 983040] + 3 ::: [232976, 983040, 232976, 983040] + 4 ::: [233208, 983040, 233208, 983040] + 5 ::: [232976, 917504, 232976, 917504] + 6 ::: [232976, 983040, 232976, 983040] + 7 ::: [232976, 917504, 232976, 917504] + 8 ::: [232976, 983040, 232976, 983040] + 9 ::: [232976, 917504, 232976, 917504] + 10 ::: [232976, 983040, 232976, 983040] 4.0.0.840, 02-jan-2018 ====================== - differences: - 0 ::: [2896, 65536, 876800, 1966080] - 1 ::: [ 0, 0, 0, 0] - 2 ::: [ 0, 0, 0, 0] - 3 ::: [ 0, 0, 0, 0] - 4 ::: [ 0, 0, 0, 0] - 5 ::: [ 0, 0, 0, 0] - 6 ::: [ 0, 0, 0, 0] - 7 ::: [ 0, 0, 0, 0] - 8 ::: [ 0, 0, 0, 0] - 9 ::: [ 0, 0, 0, 0] - 10 ::: [ 0, 0, 0, 0] - + differences: + 0 ::: [2896, 65536, 876800, 1966080] + 1 ::: [ 0, 0, 0, 0] + 2 ::: [ 0, 0, 0, 0] + 3 ::: [ 0, 0, 0, 0] + 4 ::: [ 0, 0, 0, 0] + 5 ::: [ 0, 0, 0, 0] + 6 ::: [ 0, 0, 0, 0] + 7 ::: [ 0, 0, 0, 0] + 8 ::: [ 0, 0, 0, 0] + 9 ::: [ 0, 0, 0, 0] + 10 ::: [ 0, 0, 0, 0] + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import pytest @@ -418,29 +423,44 @@ def test_1(act: Action, capsys): """ with con_worker.cursor() as cur_worker, con_dba.cursor() as cur_dba: - - ps = cur_dba.prepare(sql_memory_usage) - for i in range(N_MEASURES): - - cur_dba.execute(ps) - for r in cur_dba: - memory_diff[ i ] = r[1:] - - try: - # nb: EVERY run we force engine to compile NEW query because of changing 'i': - px = cur_worker.prepare(bad_sql % locals()) - except DatabaseError as e: - pass - - con_dba.commit() - cur_dba.execute(ps) - for r in cur_dba: - # Make subtraction for elements with same indices. - # This is DIFFERENCE between values in mon$memory_usage columns - # gathered after and before each measure: - # - memory_diff[ i ] = [a - b for a, b in zip(r[1:], memory_diff[ i ])] - + ps, rs = None, None + try: + ps = cur_dba.prepare(sql_memory_usage) + for i in range(N_MEASURES): + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur_dba.execute(ps) + for r in rs: + memory_diff[ i ] = r[1:] + + try: + # nb: EVERY run we force engine to compile NEW query because of changing 'i': + px = cur_worker.prepare(bad_sql % locals()) + except DatabaseError as x: + pass + + con_dba.commit() + rs = cur_dba.execute(ps) + for r in rs: + # Make subtraction for elements with same indices. + # This is DIFFERENCE between values in mon$memory_usage columns + # gathered after and before each measure: + # + memory_diff[ i ] = [a - b for a, b in zip(r[1:], memory_diff[ i ])] + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() memo_used_diff_list = [ v[0] for v in memory_diff.values() ] memo_allo_diff_list = [ v[1] for v in memory_diff.values() ] From 533b16f61405d4d53637618076319a063ded27fe Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 16:37:52 +0300 Subject: [PATCH 0345/1064] Added/Updated tests\bugs\core_5062_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_5062_test.py | 68 ++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_5062_test.py b/tests/bugs/core_5062_test.py index e91ab20a..353d4357 100644 --- a/tests/bugs/core_5062_test.py +++ b/tests/bugs/core_5062_test.py @@ -3,26 +3,31 @@ """ ID: issue-5349 ISSUE: 5349 -TITLE: CHAR_TO_UUID on column with index throws expression evaluation not supported - Human readable UUID argument for CHAR_TO_UUID must be of exact length 36 +TITLE: CHAR_TO_UUID on column with index throws expression evaluation not supported. Human readable UUID argument for CHAR_TO_UUID must be of exact length 36 DESCRIPTION: JIRA: CORE-5062 -FBTEST: bugs.core_5062 +NOTES: + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import pytest from firebird.qa import * +from firebird.driver import DatabaseError init_script = """ -recreate table test_uuid( - datavalue int, - uuid char(16) character set octets, - constraint test_uuid_unq unique(uuid) -); -commit; -insert into test_uuid(datavalue, uuid) values( 1, char_to_uuid('57F2B8C7-E1D8-4B61-9086-C66D1794F2D9') ); ---insert into test_uuid(datavalue, uuid) values( 2, char_to_uuid('37F2B8C3-E1D8-4B31-9083-C33D1794F2D3') ); -commit; + recreate table test_uuid( + datavalue int, + uuid char(16) character set octets, + constraint test_uuid_unq unique(uuid) + ); + commit; + insert into test_uuid(datavalue, uuid) values( 1, char_to_uuid('57F2B8C7-E1D8-4B61-9086-C66D1794F2D9') ); + commit; """ db = db_factory(init=init_script) @@ -30,11 +35,38 @@ act = python_act('db') @pytest.mark.version('>=3.0') -def test_1(act: Action): +def test_1(act: Action, capsys): with act.db.connect() as con: - c = con.cursor() - stmt = c.prepare("select datavalue from test_uuid where uuid = char_to_uuid(?)") - assert stmt.plan == 'PLAN (TEST_UUID INDEX (TEST_UUID_UNQ))' - result = c.execute(stmt, ['57F2B8C7-E1D8-4B61-9086-C66D1794F2D9']).fetchall() - assert result == [(1, )] + ps, rs = None, None + cur = con.cursor() + try: + ps = cur.prepare("select datavalue from test_uuid where uuid = char_to_uuid(?)") + print(ps.plan) + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps, ['57F2B8C7-E1D8-4B61-9086-C66D1794F2D9']) + for r in rs: + print(r[0]) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_stdout = f""" + PLAN (TEST_UUID INDEX (TEST_UUID_UNQ)) + 1 + """ + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From b1a6496fcc3b16dba70f892504703ca0e0bba8ec Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 17:04:44 +0300 Subject: [PATCH 0346/1064] Added/Updated tests\bugs\core_3977_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_3977_test.py | 72 ++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_3977_test.py b/tests/bugs/core_3977_test.py index 058ae6be..6afe14e4 100644 --- a/tests/bugs/core_3977_test.py +++ b/tests/bugs/core_3977_test.py @@ -20,6 +20,13 @@ mon$sql_text contains some KNOWN phrase - see 'HEAVY_TAG'. See function check_mon_for_pid_appearance() Checked on 3.0.12.33725, 4.0.5.3040, 5.0.0.1294, 6.0.0.172 + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import os @@ -64,32 +71,49 @@ def check_mon_for_pid_appearance(act: Action, p_async_launched: subprocess.Compl found_in_mon_tables = False with act.db.connect() as con_watcher: - custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) - tx_watcher = con_watcher.transaction_manager(custom_tpb) - cur_watcher = tx_watcher.cursor() - - ps = cur_watcher.prepare(chk_mon_sql) - - i = 0 - da = dt.now() - while True: - cur_watcher.execute(ps, (p_async_launched.pid, HEAVY_TAG,) ) - mon_result = -1 - for r in cur_watcher: - mon_result = r[0] - - tx_watcher.commit() - db = dt.now() - diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 - if mon_result == 1: - found_in_mon_tables = True - break - elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: - break + ps, rs = None, None + try: + custom_tpb = tpb(isolation = Isolation.SNAPSHOT, lock_timeout = -1) + tx_watcher = con_watcher.transaction_manager(custom_tpb) + cur_watcher = tx_watcher.cursor() + + ps = cur_watcher.prepare(chk_mon_sql) + + i = 0 + da = dt.now() + while True: + mon_result = -1 + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur_watcher.execute(ps, (p_async_launched.pid, HEAVY_TAG,) ) + for r in rs: + mon_result = r[0] + + tx_watcher.commit() + db = dt.now() + diff_ms = (db-da).seconds*1000 + (db-da).microseconds//1000 + if mon_result == 1: + found_in_mon_tables = True + break + elif diff_ms > MAX_WAIT_FOR_ISQL_PID_APPEARS_MS: + break + time.sleep(0.1) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() - time.sleep(0.1) - ps.free() assert found_in_mon_tables, f'Could not find attachment in mon$ tables for {MAX_WAIT_FOR_ISQL_PID_APPEARS_MS} ms.' From 4f6ba72bc813c5afa296546c8fbba830e332351a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 17:19:36 +0300 Subject: [PATCH 0347/1064] Added/Updated tests\bugs\core_3323_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_3323_test.py | 57 ++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_3323_test.py b/tests/bugs/core_3323_test.py index 88d8f6ce..e5ce2289 100644 --- a/tests/bugs/core_3323_test.py +++ b/tests/bugs/core_3323_test.py @@ -22,7 +22,6 @@ * every worker log must contain text 'SQLSTATE = 08003'; * no alive ISQL processes remain after issuing 'delete from mon$..' statements. JIRA: CORE-3323 -FBTEST: bugs.core_3323 NOTES: [17.11.2021] pcisar This test is too complicated and fragile (can screw the test environment) @@ -35,6 +34,13 @@ or some trouble occurs with deleting from mon$attachments. Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 (SS/CS) - both Linux and Windows. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import time import datetime as py_dt @@ -46,6 +52,7 @@ import pytest from firebird.qa import * +from firebird.driver import DatabaseError ########################### ### S E T T I N G S ### @@ -65,7 +72,7 @@ # because we kill its attachment (see 'p_isql.wait(...)'), seconds. # See also: https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait # -MAX_WAIT_FOR_ISQL_FINISH_S = 5 +MAX_WAIT_FOR_ISQL_FINISH_S = 10 init_ddl = f""" recreate table test(id int primary key using descending index test_id_desc); @@ -102,15 +109,16 @@ def test_1(act: Action, tmp_isql_cmds: List[Path], tmp_isql_logs: List[Path], ca where s.mon$attachment_id <> current_connection and s.mon$sql_text containing cast(? as varchar(20)) """ with con.cursor() as cur: - ps = cur.prepare(sql_check_appearance) - worker_att_list = [] - worker_log_list = [] - worker_pid_list = [] + ps, rs = None, None + try: + ps = cur.prepare(sql_check_appearance) + worker_att_list = [] + worker_log_list = [] + worker_pid_list = [] - for worker_i in range(0, CONCURRENT_ATT_CNT): - worker_log_list.append( open(tmp_isql_logs[worker_i], 'w') ) + for worker_i in range(0, CONCURRENT_ATT_CNT): + worker_log_list.append( open(tmp_isql_logs[worker_i], 'w') ) - try: for worker_i in range(0, CONCURRENT_ATT_CNT): if worker_i < CONCURRENT_ATT_CNT-1: @@ -147,7 +155,16 @@ def test_1(act: Action, tmp_isql_cmds: List[Path], tmp_isql_logs: List[Path], ca print(f'TIMEOUT EXPIRATION: waiting for ISQL process on iter {worker_i} took {dd} ms which exceeds limit = {MAX_WAIT_FOR_ISQL_START_MS} ms.') break - worker_att = cur.execute(ps, (f'TAG_{worker_i}',)).fetchone() + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps, (f'TAG_{worker_i}',)) + for r in rs: + worker_att = r + con.commit() if worker_att: @@ -159,23 +176,32 @@ def test_1(act: Action, tmp_isql_cmds: List[Path], tmp_isql_logs: List[Path], ca # result: all ISQLs are launched and their attachments are visible in mon$attachments (and can be traversed via worker_att_list) - ps = cur.prepare('delete from mon$attachments a where a.mon$attachment_id = ?') + kill_sttm = cur.prepare('delete from mon$attachments a where a.mon$attachment_id = ?') ################################################################### ### k i l l a t t a c h m e n t s o n e - b y - o n e ### ################################################################### for worker_id in reversed(worker_att_list): - cur.execute(ps, (worker_id,)) + cur.execute(kill_sttm, (worker_id,)) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) finally: - + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + for i,p_isql in enumerate(worker_pid_list): p_isql.wait(MAX_WAIT_FOR_ISQL_FINISH_S) print(f'returncode for ISQL worker #{i}:',p.poll()) - for f in worker_log_list: f.close() + + # All worker logs must contain 'SQLSTATE = 08003' pattern (i.e. 'connection shutdown'): p_shutdown = re.compile('SQLSTATE\\s+=\\s+08003', re.IGNORECASE) for g in worker_log_list: @@ -185,8 +211,9 @@ def test_1(act: Action, tmp_isql_cmds: List[Path], tmp_isql_logs: List[Path], ca pass else: print('Pattern ',p_shutdown,' NOT FOUND in the log ',g.name,':') + print('=== beg of log ===') print(txt) - print('='*50) + print('=== end of log ===') con.commit() # NO any ISQL worker must be alive now: From 32b76b2e5811117458c05a5c970c98a394205f6f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 18:04:48 +0300 Subject: [PATCH 0348/1064] Added/Updated tests\bugs\gh_3218_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/gh_3218_test.py | 50 +++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/tests/bugs/gh_3218_test.py b/tests/bugs/gh_3218_test.py index 3f148ef9..1fef04ed 100644 --- a/tests/bugs/gh_3218_test.py +++ b/tests/bugs/gh_3218_test.py @@ -13,11 +13,20 @@ [20.01.2024] pzotov Confirmed problem on 5.0.0.442: number of indexed reads was equal to the total count of records in rdb$relation_fields. Checked on 6.0.0.218, 5.0.1.1318. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ -import pytest from pathlib import Path + +import pytest from firebird.qa import * +from firebird.driver import DatabaseError init_sql = """ set term ^; @@ -73,22 +82,41 @@ def test_1(act: Action, capsys): result_map = {} chk_sql = 'select 1 from sp_get_relations r join rdb$relation_fields f on f.rdb$relation_name = r.rdb$relation_name where r.rdb$relation_id < 10' - with cur.prepare(chk_sql) as ps: - cur.execute(chk_sql) + ps, rs = None, None + try: + ps = cur.prepare(chk_sql) + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + tabstat1 = [ p for p in con.info.get_table_access_stats() if p.table_id == rf_rel_id ] cur.fetchall() tabstat2 = [ p for p in con.info.get_table_access_stats() if p.table_id == rf_rel_id ] print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) # explained plan, with preserving indents by replacing leading spaces with '#' - idx_reads = (tabstat2[0].indexed if tabstat2[0].indexed else 0) - if tabstat1: - idx_reads -= (tabstat1[0].indexed if tabstat1[0].indexed else 0) + idx_reads = (tabstat2[0].indexed if tabstat2[0].indexed else 0) + if tabstat1: + idx_reads -= (tabstat1[0].indexed if tabstat1[0].indexed else 0) + + print('Result:') + if idx_reads == 0 or idx_reads > cnt_chk: + print(f'POOR! Number of records in rdb$relation_fields: 1) to be filtered: {cnt_chk}, 2) total: {cnt_all}. Number of indexed_reads: {idx_reads}') + else: + print('Acceptable.') - print('Result:') - if idx_reads == 0 or idx_reads > cnt_chk: - print(f'POOR! Number of records in rdb$relation_fields: 1) to be filtered: {cnt_chk}, 2) total: {cnt_all}. Number of indexed_reads: {idx_reads}') - else: - print('Acceptable.') + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() act.expected_stdout = """ Select Expression From 028bb337805996ec188c1ddf2a9f81e5d23b2d07 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 18:10:43 +0300 Subject: [PATCH 0349/1064] Added/Updated tests\bugs\core_2477_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_2477_test.py | 78 +++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_2477_test.py b/tests/bugs/core_2477_test.py index ebaec7bc..adb14aad 100644 --- a/tests/bugs/core_2477_test.py +++ b/tests/bugs/core_2477_test.py @@ -21,20 +21,30 @@ JIRA: CORE-2477 FBTEST: bugs.core_2477 NOTES: -[16.11.2021] pcisar + [16.11.2021] pcisar This test is too complicated and fragile, and it's IMHO not worth to be implemented -[24.07.2022] pzotov + + [24.07.2022] pzotov Test was totally re-implemented. No async call of ISQL, waiting/killing etc. Checked on Windows: 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.591 Checked on Linux: 4.0.1.2692 (SS/CS) - needed to increase number of rows to be sorted. + + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import subprocess from pathlib import Path +from firebird.driver import DatabaseError +import time + import pytest from firebird.qa import * -import time init_script = """ create or alter view v_mon as @@ -108,27 +118,47 @@ def test_1(act: Action, capsys): with act.db.connect() as con_worker: cur_worker = con_worker.cursor() - cur_wrk_ps = cur_worker.prepare(heavy_sql_sttm) - - for m in ('beg','end'): - with act.db.connect() as con_monitor: - cur_monitor=con_monitor.cursor() - cur_monitor.execute('select * from v_gather_mon') - - for r in cur_monitor: - map_result[m] = (r[3], r[7]) # ('idle' | 'stalled', memo_used) - - assert map_result.get(m), f"No rows returned from v_gather_mon for m='{m}'" - - if m == 'beg': - cur_worker.execute(cur_wrk_ps) - for i in range(0, ROWS_TO_BE_SORTED): - r = cur_worker.fetchone() - - # After this loop statement with huge sort will remain in stalled state - # (its mon$statements.mon$state must be 2). - # We can now gather mon$ info second time (in a NEW connection) - # and then evaluate DIFFERENCE. + cur_wrk_ps, cur_wrk_rs = None, None + + try: + cur_wrk_ps = cur_worker.prepare(heavy_sql_sttm) + + for m in ('beg','end'): + with act.db.connect() as con_monitor: + cur_monitor=con_monitor.cursor() + cur_monitor.execute('select * from v_gather_mon') + + for r in cur_monitor: + map_result[m] = (r[3], r[7]) # ('idle' | 'stalled', memo_used) + + assert map_result.get(m), f"No rows returned from v_gather_mon for m='{m}'" + + if m == 'beg': + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + + cur_wrk_rs = cur_worker.execute(cur_wrk_ps) + for i in range(0, ROWS_TO_BE_SORTED): + r = cur_worker.fetchone() + + # After this loop statement with huge sort will remain in stalled state + # (its mon$statements.mon$state must be 2). + # We can now gather mon$ info second time (in a NEW connection) + # and then evaluate DIFFERENCE. + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if cur_wrk_rs: + cur_wrk_rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if cur_wrk_ps: + cur_wrk_ps.free() #------------------------------------------------------------------------------------------ From c5722891f9da74a087f303fac984b58886f73459 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 18:21:45 +0300 Subject: [PATCH 0350/1064] Added/Updated tests\bugs\core_1315_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection. --- tests/bugs/core_1315_test.py | 57 ++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_1315_test.py b/tests/bugs/core_1315_test.py index 7b547cc2..a1800765 100644 --- a/tests/bugs/core_1315_test.py +++ b/tests/bugs/core_1315_test.py @@ -6,9 +6,17 @@ TITLE: Data type unknown DESCRIPTION: JIRA: CORE-1315 -FBTEST: bugs.core_1315 +NOTES: + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ +from firebird.driver import DatabaseError + import pytest from firebird.qa import * @@ -16,26 +24,45 @@ act = python_act('db') -expected_stdout = """COALESCE ------------ -2 +expected_stdout = """ + COALESCE + ----------- + 2 -COALESCE ------------ -1 + COALESCE + ----------- + 1 """ @pytest.mark.version('>=3') def test_1(act: Action, capsys): with act.db.connect() as con: - c = con.cursor() - statement = c.prepare('select coalesce(?,1) from RDB$DATABASE') - c.execute(statement,[2]) - act.print_data(c) - c.execute(statement,[None]) - act.print_data(c) + cur = con.cursor() + ps, rs = None, None + try: + ps = cur.prepare('select coalesce(?,1) from RDB$DATABASE') + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps,[2]) + act.print_data(rs) + + rs = cur.execute(ps,[None]) + act.print_data(rs) + + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + act.stdout = capsys.readouterr().out act.expected_stdout = expected_stdout assert act.clean_stdout == act.clean_expected_stdout - - From 41dfa39c272cf910e1bc476f8a311c9291f39789 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 18 Jan 2025 20:38:03 +0300 Subject: [PATCH 0351/1064] Added/Updated tests\bugs\gh_8386_test.py: Removed restriction for execution only in FB 5.x after successful check on 6.0.0.585-0-6f17277. --- tests/bugs/gh_8386_test.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_8386_test.py b/tests/bugs/gh_8386_test.py index 88ee047e..cf15f52c 100644 --- a/tests/bugs/gh_8386_test.py +++ b/tests/bugs/gh_8386_test.py @@ -6,12 +6,9 @@ TITLE: Crash when creating index on table that uses UDR and ParallelWorkers > 1 DESCRIPTION: NOTES: - [17.01.2025] pzotov - Currenty fix presents only in 5.x (commit 4ddbb69). Because of that, 6.x not checked (but it is also affected). - - Confirmed bug on 5.0.2.1589, got: "SQLSTATE = 08006 / Error reading data from the connection". - Checked on 5.0.2.1592 -- all fine. - WAITING FOR FRONT-PORT FIX INTO FB 6.X. + [18.01.2025] pzotov + Confirmed bug on 5.0.2.1589, 6.0.0.584 - got: "SQLSTATE = 08006 / Error reading data ...". + Checked on 5.0.2.1592-2d11769, 6.0.0.585-6f17277 -- all fine. """ import pytest @@ -108,7 +105,7 @@ act = isql_act('db', test_script, substitutions = [('[ \t]+', ' ')]) -@pytest.mark.version('>=5.0.2,<6') +@pytest.mark.version('>=5.0.2') def test_1(act: Action): # DISABLED 17.01.2025 13:35, requested by dimitr: From e3d12fe36e8143f3a8ec40f7e06ee10923bdc32c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 19 Jan 2025 06:41:12 +0300 Subject: [PATCH 0352/1064] Added/Updated tests\bugs\core_3323_test.py: added forgotten initialization --- tests/bugs/core_3323_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_3323_test.py b/tests/bugs/core_3323_test.py index e5ce2289..a66eda82 100644 --- a/tests/bugs/core_3323_test.py +++ b/tests/bugs/core_3323_test.py @@ -162,6 +162,7 @@ def test_1(act: Action, tmp_isql_cmds: List[Path], tmp_isql_logs: List[Path], ca # causes pytest to hang on its final point. # Explained by hvlad, email 26.10.24 17:42 rs = cur.execute(ps, (f'TAG_{worker_i}',)) + worker_att = None for r in rs: worker_att = r From 7f8f2804a96fc567b5984a6c63a9961b6be2b902 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 19 Jan 2025 17:06:57 +0300 Subject: [PATCH 0353/1064] Added/Updated tests\bugs\gh_7804_test.py: Result in 6.x became equal to 5.x. Removed separation of expected* output. Checked on 6.0.0.587-90401f7 --- tests/bugs/gh_7804_test.py | 111 ++++--------------------------------- 1 file changed, 11 insertions(+), 100 deletions(-) diff --git a/tests/bugs/gh_7804_test.py b/tests/bugs/gh_7804_test.py index 7f7688b2..a32e8cf8 100644 --- a/tests/bugs/gh_7804_test.py +++ b/tests/bugs/gh_7804_test.py @@ -31,11 +31,15 @@ Output for FB 6.x will be changed later (letter from dimitr, 16.12.2023 10:32) [18.01.2025] pzotov - Resultset of cursor that executes using instance of selectable PreparedStatement must be stored - in some variable in order to have ability close it EXPLICITLY (before PS will be freed). - Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). - This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 - The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + + [19.01.2025] pzotov + Result in 6.x became equal to 5.x. Removed separation of expected* output + Checked on 6.0.0.587-90401f7 """ import pytest @@ -141,7 +145,7 @@ def test_1(act: Action, capsys): #-------------------------------------------------------------------- - expected_fb5x = f""" + expected_out = f""" Query: {q_list[0]} Select Expression ....-> Filter @@ -251,99 +255,6 @@ def test_1(act: Action, capsys): IR: 4000 """ - - expected_fb6x = f""" - Query: {q_list[0]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap - ................-> Index "TEST_X_ASC" Range Scan (full match) - NR: 0 - IR: 1000 - - Query: {q_list[1]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap Or - ................-> Bitmap - ....................-> Index "TEST_X_ASC" Range Scan (full match) - ................-> Bitmap - ....................-> Index "TEST_X_ASC" Range Scan (full match) - NR: 0 - IR: 2000 - - Query: {q_list[2]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap Or - ................-> Bitmap Or - ....................-> Bitmap - ........................-> Index "TEST_X_ASC" Range Scan (full match) - ....................-> Bitmap - ........................-> Index "TEST_X_ASC" Range Scan (full match) - ................-> Bitmap - ....................-> Index "TEST_X_ASC" Range Scan (full match) - NR: 0 - IR: 3000 - - Query: {q_list[3]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap - ................-> Index "TEST_X_ASC" Full Scan - NR: 0 - IR: 4000 - - Query: {q_list[4]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap - ................-> Index "TEST_X_DEC" Range Scan (full match) - NR: 0 - IR: 1000 - - Query: {q_list[5]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap Or - ................-> Bitmap - ....................-> Index "TEST_X_DEC" Range Scan (full match) - ................-> Bitmap - ....................-> Index "TEST_X_DEC" Range Scan (full match) - NR: 0 - IR: 2000 - - Query: {q_list[6]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap Or - ................-> Bitmap Or - ....................-> Bitmap - ........................-> Index "TEST_X_DEC" Range Scan (full match) - ....................-> Bitmap - ........................-> Index "TEST_X_DEC" Range Scan (full match) - ................-> Bitmap - ....................-> Index "TEST_X_DEC" Range Scan (full match) - NR: 0 - IR: 3000 - - Query: {q_list[7]} - Select Expression - ....-> Filter - ........-> Table "TEST" Access By ID - ............-> Bitmap - ................-> Index "TEST_X_DEC" Full Scan - NR: 0 - IR: 4000 - """ - - act.expected_stdout = expected_fb5x if act.is_version('<6') else expected_fb6x + act.expected_stdout = expected_out act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From ad0a3e851863aad5858c111b232ff0ab38ba050b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 21 Jan 2025 15:03:08 +0300 Subject: [PATCH 0354/1064] Added/Updated tests\bugs\gh_8356_test.py: Checked on 6.0.0.590-7e96b33. --- tests/bugs/gh_8356_test.py | 88 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/bugs/gh_8356_test.py diff --git a/tests/bugs/gh_8356_test.py b/tests/bugs/gh_8356_test.py new file mode 100644 index 00000000..a8d5ce12 --- /dev/null +++ b/tests/bugs/gh_8356_test.py @@ -0,0 +1,88 @@ +#coding:utf-8 + +""" +ID: issue-8356 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8356 +TITLE: Make Trace use HEX representation for parameter values of types [VAR]CHAR CHARACTER SET OCTETS and [VAR]BINARY +DESCRIPTION: +NOTES: + [21.01.2025] pzotov + After fix parameters type '[va]rchar(N) character set octets' is shown in the trace as '[var]binary(N)'. + + Confirmed problem on 6.0.0.585: parameter values in the trace are shown in binary (non-readable) form. + Checked on 6.0.0.590-7e96b33 - all fine. +""" +import re + +import pytest +from firebird.qa import * + +init_sql = """ + set term ^; + create procedure sp_test ( + a_vchr varchar(16) character set octets + ,a_chr char(16) character set octets + ,a_vbin varbinary(16) + ,a_bin binary(16) + ) as + declare n smallint; + begin + n = 1; + end + ^ + set term ;^ + commit; +""" + +db = db_factory(init = init_sql) + +act = python_act('db') + +test_sql = """ + execute procedure sp_test( + gen_uuid() + ,gen_uuid() + ,gen_uuid() + ,gen_uuid() + ); +""" + +trace_events_lst = \ + [ 'time_threshold = 0' + ,'log_procedure_start = true' + ,'log_initfini = false' + ] + +@pytest.mark.trace +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + with act.trace(db_events = trace_events_lst): + act.reset() + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + + # Process trace + # BEFORE FIX: param0 = varchar(16), "" + # AFTER FIX: param0 = varbinary(16), "D0EC952EC11A4C209011CF95C1712D2F" + + param_name_pattern = re.compile( r'\s?param\d+\s?=\s?(var)?(binary|char)\(\d+\)', re.IGNORECASE ) + # param_hexvalue_ptn = re.compile('') + + for line in act.trace_log: + if param_name_pattern.search(line.lower()): + param_name = line.split("=")[0].strip() + param_val = line.split('"')[1] + try: + _ = int(param_val, 16) + print(f'Parameter: {param_name}, value is in HEX form.') + except ValueError as e: + print(f'Parameter: {param_name}, value: "{param_val}" - not in HEX form.') + + act.expected_stdout = """ + Parameter: param0, value is in HEX form. + Parameter: param1, value is in HEX form. + Parameter: param2, value is in HEX form. + Parameter: param3, value is in HEX form. + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 96ccb8a1f3fb94e9951468a328e040a37b631beb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 21 Jan 2025 18:59:32 +0300 Subject: [PATCH 0355/1064] Added/Updated tests\bugs\gh_8356_test.py: Reduced min_version to 5.0a after succcessful check on intermediade snapshot 5.0.2.1597-4fa00f1 --- tests/bugs/gh_8356_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8356_test.py b/tests/bugs/gh_8356_test.py index a8d5ce12..dded932f 100644 --- a/tests/bugs/gh_8356_test.py +++ b/tests/bugs/gh_8356_test.py @@ -10,7 +10,7 @@ After fix parameters type '[va]rchar(N) character set octets' is shown in the trace as '[var]binary(N)'. Confirmed problem on 6.0.0.585: parameter values in the trace are shown in binary (non-readable) form. - Checked on 6.0.0.590-7e96b33 - all fine. + Checked on 6.0.0.590-7e96b33, 5.0.2.1597-4fa00f1 - all fine. """ import re @@ -54,7 +54,7 @@ ] @pytest.mark.trace -@pytest.mark.version('>=6.0') +@pytest.mark.version('>=5.0.2') def test_1(act: Action, capsys): with act.trace(db_events = trace_events_lst): From 87def8d0b8a887c76f99f294a43d9768c94c1dbc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 22 Jan 2025 11:05:14 +0300 Subject: [PATCH 0356/1064] Added/Updated tests\bugs\gh_8394_test.py: Checked on 5.0.2.1601, 6.0.0.594 --- tests/bugs/gh_8394_test.py | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tests/bugs/gh_8394_test.py diff --git a/tests/bugs/gh_8394_test.py b/tests/bugs/gh_8394_test.py new file mode 100644 index 00000000..714325c4 --- /dev/null +++ b/tests/bugs/gh_8394_test.py @@ -0,0 +1,96 @@ +#coding:utf-8 + +""" +ID: issue-8394 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8394 +TITLE: Make Trace use HEX representation for parameter values of types [VAR]CHAR CHARACTER SET OCTETS and [VAR]BINARY +DESCRIPTION: +NOTES: + [22.01.2025] pzotov + Checked on 5.0.2.1601, 6.0.0.594 +""" +import re + +import pytest +from firebird.qa import * + +db = db_factory(page_size = 8192) + +substitutions = [ + ( r'Blobs:\s+\d+,\s+total\s+length:\s+\d+,\s+blob\s+pages:\s+\d+', 'Blobs: N, total length: M, blob pages: P') + ,( r'\d+,\s+total\s+length: \d+,\s+blob\s+pages:\s+\d+', 'X, total length: M, blob pages: P') +] +act = python_act('db', substitutions = substitutions) + +test_sql = """ + recreate sequence g; + recreate table test(id int, b blob); + + -- https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref30/fblangref30-datatypes-bnrytypes.html + -- 3.7.2. BLOB Specifics / BLOB Storage + -- * By default, a regular record is created for each BLOB and it is stored on a data page that is allocated for it. + -- If the entire BLOB fits onto this page, it is called a level 0 BLOB. + -- * The number of this special record is stored in the table record and occupies 8 bytes. + -- If a BLOB does not fit onto one data page, its contents are put onto separate pages allocated exclusively to it (blob pages), + -- while the numbers of these pages are stored into the BLOB record. This is a level 1 BLOB. + -- * If the array of page numbers containing the BLOB data does not fit onto a data page, the array is put on separate blob pages, + -- while the numbers of these pages are put into the BLOB record. This is a level 2 BLOB. + + set term ^; + execute block as + declare n int; + begin + insert into test(id, b) values(gen_id(g,1), gen_uuid()); + insert into test(id, b) + values( + gen_id(g,1) + ,(select list(gen_uuid()) as s from rdb$types,rdb$types) + ); + + insert into test(id, b) + values( + gen_id(g,1) + ,(select list(gen_uuid()) as s from (select 1 x from rdb$types,rdb$types,rdb$types rows 800000)) + ); + end + ^ + set term ;^ + commit; +""" + +@pytest.mark.version('>=5.0.2') +def test_1(act: Action, capsys): + + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + + # Pipe of command to ISQL before 6.x leads to appearing of following 'noise info': + # Database: localhost:..., User: SYSDBA + # SQL> SQL> SQL> SQL> SQL> SQL> SQL> ... + # We have to use 'clean_stdout' in order to ignore this: + assert act.clean_stdout == '' + act.reset() + + #--------------------------------------------------------------------------------- + + blob_overall_info_ptn = re.compile( r'Blobs:\s+\d+,\s+total\s+length:\s+\d+,\s+blob\s+pages', re.IGNORECASE ) + blob_level_info_ptn = re.compile( r'Level\s+\d+: \d+,\s+total\s+length: \d+,\s+blob\s+pages', re.IGNORECASE ) + + act.gstat(switches=['-r']) + blob_overall_found = False + for line in act.stdout.splitlines(): + if blob_overall_info_ptn.search(line): + blob_overall_found = True + print(line) + if blob_overall_found: + if blob_level_info_ptn.search(line): + print(line) + + + act.expected_stdout = """ + Blobs: N, total length: M, blob pages: P + Level 0: X, total length: M, blob pages: P + Level 1: X, total length: M, blob pages: P + Level 2: X, total length: M, blob pages: P + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 4fa41e56f437940d6d53da3731b43d88b333d4f3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 22 Jan 2025 11:09:45 +0300 Subject: [PATCH 0357/1064] Added/Updated tests\bugs\gh_8394_test.py: added pattern for check message with table size --- tests/bugs/gh_8394_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/bugs/gh_8394_test.py b/tests/bugs/gh_8394_test.py index 714325c4..11fe2335 100644 --- a/tests/bugs/gh_8394_test.py +++ b/tests/bugs/gh_8394_test.py @@ -19,6 +19,7 @@ substitutions = [ ( r'Blobs:\s+\d+,\s+total\s+length:\s+\d+,\s+blob\s+pages:\s+\d+', 'Blobs: N, total length: M, blob pages: P') ,( r'\d+,\s+total\s+length: \d+,\s+blob\s+pages:\s+\d+', 'X, total length: M, blob pages: P') + ,( r'Table\s+size:\s+\d+\s+bytes', 'Table size: N bytes') ] act = python_act('db', substitutions = substitutions) @@ -74,6 +75,7 @@ def test_1(act: Action, capsys): blob_overall_info_ptn = re.compile( r'Blobs:\s+\d+,\s+total\s+length:\s+\d+,\s+blob\s+pages', re.IGNORECASE ) blob_level_info_ptn = re.compile( r'Level\s+\d+: \d+,\s+total\s+length: \d+,\s+blob\s+pages', re.IGNORECASE ) + table_size_ptn = re.compile( r'Table\s+size:\s+\d+\s+bytes', re.IGNORECASE ) act.gstat(switches=['-r']) blob_overall_found = False @@ -84,6 +86,8 @@ def test_1(act: Action, capsys): if blob_overall_found: if blob_level_info_ptn.search(line): print(line) + if table_size_ptn.search(line): + print(line) act.expected_stdout = """ @@ -91,6 +95,7 @@ def test_1(act: Action, capsys): Level 0: X, total length: M, blob pages: P Level 1: X, total length: M, blob pages: P Level 2: X, total length: M, blob pages: P + Table size: N bytes """ act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 48c58e42e4b1cb181752c9603d104a9cdc222b19 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 23 Jan 2025 11:01:19 +0300 Subject: [PATCH 0358/1064] Added/Updated tests\bugs\gh_8409_test.py: Checked on 6.0.0.595-2c5b146 (intermediate snapshot, UTC 20250123 01:49). --- tests/bugs/gh_8409_test.py | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/bugs/gh_8409_test.py diff --git a/tests/bugs/gh_8409_test.py b/tests/bugs/gh_8409_test.py new file mode 100644 index 00000000..f226ab91 --- /dev/null +++ b/tests/bugs/gh_8409_test.py @@ -0,0 +1,62 @@ +#coding:utf-8 + +""" +ID: issue-8409 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8409 +TITLE: Error message "SQL -104 / Unexpected end of command" appears in a trace log when 'SET AUTOTERM ON;' is used +DESCRIPTION: Test checks that trace will not contain error messages caused by DDL prepare. Expected output is empty. +NOTES: + [23.01.2025] pzotov + Checked on 6.0.0.595-2c5b146 (intermediate snapshot, UTC 20250123 01:49). +""" +import re + +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db') + +test_sql = """ +set autoterm on; +create procedure sp_test1 as + declare n smallint; +begin + n = 1; +end;create procedure sp_test2 as declare n smallint;begin n = 2;end + +; +""" + +trace_events_lst = \ + [ 'time_threshold = 0' + ,'log_errors = true' + ,'log_statement_prepare = true' + ,'log_initfini = false' + ] + +@pytest.mark.trace +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + with act.trace(db_events = trace_events_lst): + act.reset() + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + + allowed_patterns = [ + 'ERROR AT JStatement::prepare' + ,'335544569 : Dynamic SQL Error' + ,'335544436 : SQL error code = -104' + ,'335544851 : Unexpected end of command' + ] + allowed_patterns = [re.compile(p, re. IGNORECASE) for p in allowed_patterns] + + + for line in act.trace_log: + for p in allowed_patterns: + if p.search(line): + print('UNEXPECTED: '+line) + + act.expected_stdout = "" + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From a25879cc4a564e1068ddb33b6cb01468d73f15d0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 23 Jan 2025 14:21:33 +0300 Subject: [PATCH 0359/1064] Added/Updated tests\bugs\gh_8391_test.py: Checked on 6.0.0.590 -- all OK. --- tests/bugs/gh_8391_test.py | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 tests/bugs/gh_8391_test.py diff --git a/tests/bugs/gh_8391_test.py b/tests/bugs/gh_8391_test.py new file mode 100644 index 00000000..d4dd685f --- /dev/null +++ b/tests/bugs/gh_8391_test.py @@ -0,0 +1,136 @@ +#coding:utf-8 + +#coding:utf-8 + +""" +ID: issue-8391 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8391 +TITLE: gbak: Incorrect total statistics for restore +DESCRIPTION: + Test uses pre-created databases.conf which has alias (see variable REQUIRED_ALIAS) with DefaultDbCachePages = 128. + Database file for that alias must NOT exist in the QA_root/files/qa/ subdirectory: it will be created here. + + We add data to test DB (script was taken from gh_8394_test.py - it is enough to use it instead of bug DB from ticket). + Then we make backup and start restore with '-v -st w' option. + Parsing of restore log must give us total number of writes that were done, see variable 'gbak_total_writes'. + Value of gbak_total_writes must be NOT LESS than ratio restored_file_size / PAGE_SIZE. +NOTES: + [23.01.2025] pzotov + 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. + 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf + (for LINUX this equality is case-sensitive, even when aliases are compared!) + 3. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). + Discussed with pcisar, letters since 30-may-2022 13:48, subject: + "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" + 4. Value of DefaultDBCachePages must be LESS than result of division restored_file_size/PAGE_SIZE otherwise fix can not be observed. + + Confirmed problem on 6.0.0.584 (only when Servermode = 'Super'; SC and CS not affected). + Checked on 6.0.0.590 -- all OK. +""" + +import locale +import re +import os +from pathlib import Path + +import pytest +from firebird.qa import * + +substitutions = [('[ \t]+', ' '), ] + +PAGE_SIZE = 8192 +REQUIRED_ALIAS = 'tmp_gh_8391_alias' + +db = db_factory(filename = '#' + REQUIRED_ALIAS, do_not_create = True, do_not_drop = True) +act = python_act('db', substitutions = substitutions) + +tmp_fbk = temp_file('tmp_gh_8391.restored.fbk') +tmp_log = temp_file('tmp_gh_8391.restored.log') + +@pytest.mark.version('>=6.0') +def test_1(act: Action, tmp_fbk: Path, tmp_log: Path, capsys): + + if act.get_server_architecture() != 'SuperServer': + pytest.skip('Applies only to SuperServer') + + # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_8391_alias = $(dir_sampleDb)/qa/tmp_qa_8391.fdb + # - then we extract filename: 'tmp_qa_8391.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + test_sql = f""" + set list on; + create database '{REQUIRED_ALIAS}' user {act.db.user} password '{act.db.password}' page_size {PAGE_SIZE}; + commit; + recreate sequence g; + recreate table test(id int, b blob); + + set autoterm on; + execute block as + declare n int; + begin + insert into test(id, b) values(gen_id(g,1), gen_uuid()); + insert into test(id, b) + values( + gen_id(g,1) + ,(select list(gen_uuid()) as s from rdb$types,rdb$types) + ); + + insert into test(id, b) + values( + gen_id(g,1) + ,(select list(gen_uuid()) as s from (select 1 x from rdb$types,rdb$types,rdb$types rows 800000)) + ); + end + ; + commit; + select mon$database_name, mon$page_buffers from mon$database; + """ + + test_fdb_file = 'UNDEFINED' + act.isql(switches=['-q'], input = test_sql, connect_db = False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) + for line in act.stdout.splitlines(): + if line.startswith('mon$database_name'.upper()): + test_fdb_file = line.split()[1] + if line.startswith('mon$page_buffers'.upper()): + test_fdb_buffers = int(line.split()[1]) + + assert test_fdb_buffers == 128 + act.reset() + + act.gbak(switches=['-b', act.db.dsn, str(tmp_fbk)], combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == '' + act.reset() + + act.gbak(switches=['-rep', '-v', '-st', 'w', str(tmp_fbk), REQUIRED_ALIAS], combine_output = True, io_enc = locale.getpreferredencoding()) + + # gbak: NNNN total statistics + gbak_write_total_stat_ptn = re.compile( r'gbak(:)?\s+\d+\s+total\s+statistics', re.IGNORECASE ) + + EXPECTED_MSG = 'EXPECTED: gbak total statistics for writes NOT LESS than ratio DB_FILE_SIZE / PAGE_SIZE' + for line in act.stdout.splitlines(): + if gbak_write_total_stat_ptn.search(line): + gbak_total_writes = int(line.split()[1]) + restored_file_size = os.stat(test_fdb_file).st_size + if gbak_total_writes >= restored_file_size / PAGE_SIZE: + print(EXPECTED_MSG) + else: + print(f'UNEXPECTED: {gbak_total_writes=} -- LESS than {restored_file_size/PAGE_SIZE=}') + + act.expected_stdout = EXPECTED_MSG + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 182c6cd2d30c9e3a89e6f8871e3cf47c21b2758d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 23 Jan 2025 14:36:04 +0300 Subject: [PATCH 0360/1064] Added/Updated tests\bugs\gh_8391_test.py: reduced min_version to 4.0.6 after reproducing bug on 5.0.2.1592 and fix on 5.0.2.1601. FB-4.x seems not affected, checked on 4.0.6.3174-ffd396f, date: 23-dec-2024 --- tests/bugs/gh_8391_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_8391_test.py b/tests/bugs/gh_8391_test.py index d4dd685f..0f978940 100644 --- a/tests/bugs/gh_8391_test.py +++ b/tests/bugs/gh_8391_test.py @@ -24,8 +24,8 @@ "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" 4. Value of DefaultDBCachePages must be LESS than result of division restored_file_size/PAGE_SIZE otherwise fix can not be observed. - Confirmed problem on 6.0.0.584 (only when Servermode = 'Super'; SC and CS not affected). - Checked on 6.0.0.590 -- all OK. + Confirmed problem on 6.0.0.584, 5.0.2.1592 (only when Servermode = 'Super'; SC and CS not affected). + Checked on 6.0.0.590, 5.0.2.1601 -- all OK; 4.x. seems not affected (checked on 4.0.6.3174-ffd396f, date: 23-dec-2024). """ import locale @@ -47,7 +47,7 @@ tmp_fbk = temp_file('tmp_gh_8391.restored.fbk') tmp_log = temp_file('tmp_gh_8391.restored.log') -@pytest.mark.version('>=6.0') +@pytest.mark.version('>=4.0.6') def test_1(act: Action, tmp_fbk: Path, tmp_log: Path, capsys): if act.get_server_architecture() != 'SuperServer': From 61dc63016ab608d82c71234db343f70a6a7819f4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 24 Jan 2025 10:24:08 +0300 Subject: [PATCH 0361/1064] Added section to databases.conf that is needed for test #8391 --- files/qa-databases.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index cf6c7d58..b5d90b1a 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -280,6 +280,11 @@ tmp_gh_8253_alias = $(dir_sampleDb)/qa/tmp_gh_8253.fdb SecurityDatabase = tmp_gh_8253_alias } +# Test issue: https://github.com/FirebirdSQL/firebird/issues/8391 +tmp_gh_8391_alias = $(dir_sampleDb)/qa/tmp_gh_8391.fdb +{ + DefaultDbCachePages = 128 +} # Databases for replication tests: # From 6f18e25e1c645ba076329faf5a58c5640248d200 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 3 Feb 2025 20:21:57 +0300 Subject: [PATCH 0362/1064] Added/Updated tests\bugs\gh_8109_test.py: Checked on 6.0.0.601-5dee439, 5.0.2.1606-fd31e52 (intermediate snapshots). --- tests/bugs/gh_8109_test.py | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tests/bugs/gh_8109_test.py diff --git a/tests/bugs/gh_8109_test.py b/tests/bugs/gh_8109_test.py new file mode 100644 index 00000000..75cab225 --- /dev/null +++ b/tests/bugs/gh_8109_test.py @@ -0,0 +1,155 @@ +#coding:utf-8 + +""" +ID: issue-8109 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8109 +TITLE: Plan/Performance regression when using special construct for IN in FB5.x compared to FB3.x +DESCRIPTION: +NOTES: + [03.02.2025] pzotov + Confirmed problem (regression) on 6.0.0.595-2c5b146, 5.0.2.1601-f094936 + Checked on 6.0.0.601-5dee439, 5.0.2.1606-fd31e52 (intermediate snapshots). +""" + +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError + +init_sql = """ + create table test(x int, y int, u int, v int, p int, q int); + insert into test(x,y, u,v, p,q) select r,r, r,r, r,r from ( select rand()*10000 r from rdb$types, rdb$types ); + commit; + create index test_x_asc on test(x); + create index test_y_asc on test(y); + create index test_c_asc on test computed by (x+y); + create index test_p_asc on test(p) where p < 5001; -- partial index + create index test_q_asc on test(q) where q > 4999; -- partial index + + create descending index test_u_dec on test(u); + create descending index test_v_dec on test(v); + create descending index test_c_dec on test computed by (u-v); + create descending index test_p_dec on test(p) where p > 4999; -- partial index + create descending index test_q_dec on test(q) where q < 5001; -- partial index + 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('>=3') +def test_1(act: Action, capsys): + queries_map = { i : x for i,x in enumerate + ( + [ + 'select * from test where 5000 in (x, y)' + ,'select * from test where 5000 in (u, v)' + ,'select * from test where 5000 in (x, u)' + ,'select * from test where 5000 in (v, y)' + ,'select * from test where 5000 in (x+y, u-v)' + ,'select * from test where 5000 in (p, q) and p < 5001 and q > 4999' + ,'select * from test where 5000 in (p, q) and p > 4999 and q < 5001' + ] + ) + } + with act.db.connect() as con: + cur = con.cursor() + for qry_idx, qry_txt in queries_map.items(): + ps = None + try: + ps = cur.prepare(qry_txt) + + # Print explained plan with padding eash line by dots in order to see indentations: + print(qry_txt) + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + print('\n') + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if ps: + ps.free() + + + expected_stdout = f""" + {queries_map[ 0 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_Y_ASC" Range Scan (full match) + + {queries_map[ 1 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_U_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_V_DEC" Range Scan (full match) + + {queries_map[ 2 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_U_DEC" Range Scan (full match) + + {queries_map[ 3 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_V_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_Y_ASC" Range Scan (full match) + + {queries_map[ 4 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_C_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_C_DEC" Range Scan (full match) + + {queries_map[ 5 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_P_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_Q_ASC" Range Scan (full match) + + {queries_map[ 6 ]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TEST_P_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TEST_Q_DEC" Range Scan (full match) + """ + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From be5952b164027ab76ad43bf4df17aaf19a4eaf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20C=C3=ADsa=C5=99?= Date: Mon, 3 Feb 2025 19:21:06 +0100 Subject: [PATCH 0363/1064] Create FUNDING.yml --- .github/FUNDING.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..cc93cff0 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +thanks_dev: # Replace with a single thanks.dev username +custom: https://firebirdsql.org/en/donate/ From 2d6fec224e547cadf128f1f2147b9b4e415caceb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 4 Feb 2025 10:54:37 +0300 Subject: [PATCH 0364/1064] Added/Updated tests\bugs\gh_7466_plans_tracking_test.py: changed explained plan for 'EXISTS()' subquery of recursive SQL -- see notes. Related to 0cc77c89 ('Fix #8109: Plan/Performance regression ...') --- tests/bugs/gh_7466_plans_tracking_test.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_7466_plans_tracking_test.py b/tests/bugs/gh_7466_plans_tracking_test.py index a745649c..b9913aa9 100644 --- a/tests/bugs/gh_7466_plans_tracking_test.py +++ b/tests/bugs/gh_7466_plans_tracking_test.py @@ -46,6 +46,9 @@ https://github.com/FirebirdSQL/firebird/commit/ae427762d5a3e740b69c7239acb9e2383bc9ca83 // 5.x https://github.com/FirebirdSQL/firebird/commit/f647dfd757de3c4065ef2b875c95d19311bb9691 // 6.x + [04-feb-2025] + Adjusted execution plan for EXISTS() part of recursive query: "List Scan" was replaced with "Range Scan" for + "and m0a.x in (dx.y, dx.z)". This change caused by commit 0cc77c89 ("Fix #8109: Plan/Performance regression ...") """ import locale import re @@ -136,8 +139,10 @@ def test_1(act: Action, capsys): -- https://github.com/FirebirdSQL/firebird/commit/5df6668c7bf5a4b27e15f687f8c6cc40e260ced8 -- (Allow computable but non-invariant lists to be used for index lookup) -- See also: tests/functional/tabloid/test_e260ced8.py - -- Here "Index "TMAIN_X" List Scan (full match)" will be! - -- Old: "Index "TMAIN_X" Range Scan (full match)" + -- ######################################################################################## + -- NOTE! + -- Before 03-feb-2025 "Index "TMAIN_X" List Scan (full match)" was here, but since 0cc77c89 + -- bitmap_Or for two scans will be performed ("Index "TMAIN_X" Range Scan (full match)"). and m0a.x in (dx.y, dx.z) -- ### ATTENTION ### ) ) @@ -217,8 +222,11 @@ def test_1(act: Action, capsys): Sub-query ....-> Filter ........-> Table "TMAIN" as "R M0A" Access By ID - ............-> Bitmap - ................-> Index "TMAIN_X" List Scan (full match) + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "TMAIN_X" Range Scan (full match) + ................-> Bitmap + ....................-> Index "TMAIN_X" Range Scan (full match) Select Expression(line, column) ....-> Singularity Check ........-> Aggregate From d082d444029eada230c6c635dc3f155c39b78084 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 4 Feb 2025 11:00:19 +0300 Subject: [PATCH 0365/1064] Added/Updated tests\functional\tabloid\test_e260ced8.py: changed explained plan for 'EXISTS()' subquery of recursive SQL -- see notes. Related to 0cc77c89 ('Fix #8109: Plan/Performance regression ...') --- tests/functional/tabloid/test_e260ced8.py | 30 +++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/functional/tabloid/test_e260ced8.py b/tests/functional/tabloid/test_e260ced8.py index 60b46e21..4b7f3b8c 100644 --- a/tests/functional/tabloid/test_e260ced8.py +++ b/tests/functional/tabloid/test_e260ced8.py @@ -6,7 +6,7 @@ TITLE: Allow computable but non-invariant lists to be used for index lookup DESCRIPTION: NOTES: - [08.09.2023] + [08.09.2023] pzotov Before improvement explained plan was: ======= Sub-query @@ -32,6 +32,11 @@ (it is desirable to leading indents). Checked on 5.0.0.1190. + + [04.02.2025] pzotov + Adjusted execution plan for EXISTS() part of recursive query: "List Scan" was replaced with "Range Scan" for + "where b.x in (a.x, 2*a.x, 3*a.x)". This change caused by commit 0cc77c89 ("Fix #8109: Plan/Performance regression ...") + Checked on 6.0.0.607-1985b88, 5.0.2.1610-5e63ad0 """ import pytest @@ -50,7 +55,7 @@ act = python_act('db') -def replace_leading(source, char="#"): +def replace_leading(source, char="."): stripped = source.lstrip() return char * (len(source) - len(stripped)) + stripped @@ -63,19 +68,28 @@ def test_1(act: Action, capsys): where exists( select * from t1 b + -- 04-feb-2025: bitmap_Or for three values will be used here since commit + -- 0cc77c89 ('Fix #8109: Plan/Performance regression ...') + -- Before this change plan has: 'Index "T1_X" List Scan (full match)' where b.x in (a.x, 2*a.x, 3*a.x) ) """ act.expected_stdout = """ Sub-query - ####-> Filter - ########-> Table "T1" as "B" Access By ID - ############-> Bitmap - ################-> Index "T1_X" List Scan (full match) + ....-> Filter + ........-> Table "T1" as "B" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "T1_X" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "T1_X" Range Scan (full match) + ................-> Bitmap + ....................-> Index "T1_X" Range Scan (full match) Select Expression - ####-> Filter - ########-> Table "T1" as "A" Full Scan + ....-> Filter + ........-> Table "T1" as "A" Full Scan """ with act.db.connect() as con: cur = con.cursor() From a2ee2e0dac43814e3f2198eb69fc75ef770ca43b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 5 Feb 2025 11:23:56 +0300 Subject: [PATCH 0366/1064] Added/Updated tests\bugs\gh_8109_test.py: fix forgotten min_version: must be at least 5.0.2 --- tests/bugs/gh_8109_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8109_test.py b/tests/bugs/gh_8109_test.py index 75cab225..8608ea54 100644 --- a/tests/bugs/gh_8109_test.py +++ b/tests/bugs/gh_8109_test.py @@ -44,7 +44,7 @@ def replace_leading(source, char="."): #----------------------------------------------------------- -@pytest.mark.version('>=3') +@pytest.mark.version('>=5.0.2') def test_1(act: Action, capsys): queries_map = { i : x for i,x in enumerate ( From 1df797523d7c3f090aeaa74e6ce6bbd27ed5ecb5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 6 Feb 2025 09:27:03 +0300 Subject: [PATCH 0367/1064] Added/Updated tests\bugs\core_1539_test.py: adjusted code, added comments --- tests/bugs/core_1539_test.py | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/bugs/core_1539_test.py b/tests/bugs/core_1539_test.py index 8e3db6c4..5a9ed57a 100644 --- a/tests/bugs/core_1539_test.py +++ b/tests/bugs/core_1539_test.py @@ -2,9 +2,11 @@ """ ID: issue-1957 -ISSUE: 1957 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1957 TITLE: select * from rdb$triggers where rdb$trigger_source like 'CHECK%' DESCRIPTION: + presence of '%' at the end of LIKE pattern causes + "arithmetic exception, numeric overflow, or string truncation. Cannot transliterate character between character sets" JIRA: CORE-1539 FBTEST: bugs.core_1539 """ @@ -13,9 +15,9 @@ from firebird.qa import * init_script = """ - -- ### ONCE AGAIN ### - -- 1) for checking this under ISQL following must be encoded in WIN1251 - -- 2) for running under fbt_run utility following must be encoded in UTF8. + -- note: + -- for checking this under ISQL following must be encoded in WIN1251 + -- for running under fbt_run utility following must be encoded in UTF8. recreate table test ( bugtype varchar(20), bugfrequency varchar(20), @@ -36,53 +38,51 @@ db = db_factory(charset='UTF8', init=init_script) test_script = """ -set blob all; -set list on; --- Ticket: --- select * from rdb$triggers where rdb$trigger_source like 'CHECK%%' ==> "Cannot transliterate character between character sets." --- select * from rdb$triggers where rdb$trigger_source starting 'CHECK' ==> works fine. -select rdb$trigger_name, rdb$trigger_source -from rdb$triggers -where rdb$trigger_source like 'check%%' -order by cast(replace(rdb$trigger_name, 'CHECK_', '') as int); + set blob all; + set list on; + -- Ticket: + -- select * from rdb$triggers where rdb$trigger_source like 'CHECK%%' ==> "Cannot transliterate character between character sets." + -- select * from rdb$triggers where rdb$trigger_source starting 'CHECK' ==> works fine. + select rdb$trigger_name, rdb$trigger_source as trg_source_blob_id + from rdb$triggers + where rdb$trigger_source like 'check%%' + order by rdb$trigger_name; """ -act = isql_act('db', test_script, - substitutions=[('RDB$TRIGGER_SOURCE.*', 'RDB$TRIGGER_SOURCE ')]) +act = isql_act('db', test_script, substitutions=[('TRG_SOURCE_BLOB_ID .*', 'TRG_SOURCE_BLOB_ID')]) expected_stdout = """ + RDB$TRIGGER_NAME CHECK_1 + TRG_SOURCE_BLOB_ID 0:b + check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) -RDB$TRIGGER_NAME CHECK_1 -RDB$TRIGGER_SOURCE 0:b -check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) + RDB$TRIGGER_NAME CHECK_2 + TRG_SOURCE_BLOB_ID 0:e + check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) -RDB$TRIGGER_NAME CHECK_2 -RDB$TRIGGER_SOURCE 0:e -check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) + RDB$TRIGGER_NAME CHECK_3 + TRG_SOURCE_BLOB_ID 0:11 + check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) -RDB$TRIGGER_NAME CHECK_3 -RDB$TRIGGER_SOURCE 0:11 -check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) + RDB$TRIGGER_NAME CHECK_4 + TRG_SOURCE_BLOB_ID 0:14 + check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) -RDB$TRIGGER_NAME CHECK_4 -RDB$TRIGGER_SOURCE 0:14 -check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) + RDB$TRIGGER_NAME CHECK_5 + TRG_SOURCE_BLOB_ID 0:17 + check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) -RDB$TRIGGER_NAME CHECK_5 -RDB$TRIGGER_SOURCE 0:17 -check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) + RDB$TRIGGER_NAME CHECK_6 + TRG_SOURCE_BLOB_ID 0:1a + check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) -RDB$TRIGGER_NAME CHECK_6 -RDB$TRIGGER_SOURCE 0:1a -check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) + RDB$TRIGGER_NAME CHECK_7 + TRG_SOURCE_BLOB_ID 0:1d + check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) -RDB$TRIGGER_NAME CHECK_7 -RDB$TRIGGER_SOURCE 0:1d -check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) - -RDB$TRIGGER_NAME CHECK_8 -RDB$TRIGGER_SOURCE 0:20 -check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) + RDB$TRIGGER_NAME CHECK_8 + TRG_SOURCE_BLOB_ID 0:20 + check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) """ @pytest.mark.version('>=3') From 7c6655190f7d39edd9263259f11a79d1aebc5bd4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 6 Feb 2025 09:34:34 +0300 Subject: [PATCH 0368/1064] Added/Updated tests\bugs\core_2258_test.py: adjusted code: changed output to SET LIST ON, added substitutions to filter out blob IDs --- tests/bugs/core_2258_test.py | 75 +++++++++++++++--------------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/tests/bugs/core_2258_test.py b/tests/bugs/core_2258_test.py index 0b5c3f34..23d6ed0c 100644 --- a/tests/bugs/core_2258_test.py +++ b/tests/bugs/core_2258_test.py @@ -2,7 +2,7 @@ """ ID: issue-2684 -ISSUE: 2684 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/2684 TITLE: Internal error when select upper() from union DESCRIPTION: JIRA: CORE-2258 @@ -14,53 +14,40 @@ db = db_factory() -test_script = """SELECT * FROM - ( - SELECT CAST('123' AS BLOB SUB_TYPE TEXT) FROM RDB$DATABASE - UNION ALL - SELECT CAST('123' AS BLOB SUB_TYPE TEXT) FROM RDB$DATABASE - ) AS R (BLOB_FIELD) -; - -SELECT UPPER(BLOB_FIELD) FROM - ( - SELECT CAST('123' AS BLOB SUB_TYPE TEXT) FROM RDB$DATABASE - UNION ALL - SELECT CAST('123' AS BLOB SUB_TYPE TEXT) FROM RDB$DATABASE - ) AS R (BLOB_FIELD) -; +test_script = """ + set list on; + set count on; + select * from + ( + select cast('123' as blob sub_type text) from rdb$database + union all + select cast('123' as blob sub_type text) from rdb$database + ) as r (blob_field_id) + ; + + select upper(blob_field) from + ( + select cast('123' as blob sub_type text) from rdb$database + union all + select cast('123' as blob sub_type text) from rdb$database + ) as r (blob_field) + ; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [('BLOB_FIELD_ID .*', 'BLOB_FIELD_ID'), ('UPPER.*', 'UPPER')]) expected_stdout = """ - BLOB_FIELD -================= - 0:1 -============================================================================== -BLOB_FIELD: -123 -============================================================================== - 0:2 -============================================================================== -BLOB_FIELD: -123 -============================================================================== - - - UPPER -================= - 0:7 -============================================================================== -UPPER: -123 -============================================================================== - 0:a -============================================================================== -UPPER: -123 -============================================================================== - + BLOB_FIELD_ID 0:1 + 123 + BLOB_FIELD_ID 0:3 + 123 + Records affected: 2 + + UPPER 0:7 + 123 + UPPER 0:b + 123 + Records affected: 2 """ @pytest.mark.version('>=3.0') From 810ed6437092c048185dbb40820cdf08b9085b6f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 6 Feb 2025 09:38:59 +0300 Subject: [PATCH 0369/1064] Added/Updated tests\bugs\core_3601_test.py: added substitutions to filter out blob IDs for 'MEMO_WIN1250' column --- tests/bugs/core_3601_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3601_test.py b/tests/bugs/core_3601_test.py index a86d631a..eac82da4 100644 --- a/tests/bugs/core_3601_test.py +++ b/tests/bugs/core_3601_test.py @@ -2,7 +2,7 @@ """ ID: issue-3955 -ISSUE: 3955 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/3955 TITLE: Incorrect TEXT BLOB charset transliteration on VIEW with trigger DESCRIPTION: Test verifies that all OK when connection charset = UTF8 @@ -281,7 +281,7 @@ from v_t_test; """ -act = isql_act('db', test_script, substitutions=[('MEMO_UTF8.*', 'MEMO_UTF8')]) +act = isql_act('db', test_script, substitutions=[ ('MEMO_UTF8.*', 'MEMO_UTF8'), ('MEMO_WIN1250.*', 'MEMO_WIN1250') ]) expected_stdout = """ ID 1 From 81f5b34ed951f7eab091c9f80713f743c58ccc65 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 7 Feb 2025 12:03:45 +0300 Subject: [PATCH 0370/1064] Added/Updated tests\bugs\core_2966_test.py: added 'combine_output = True' and 'io_enc = locale.getpreferredencoding()'. See comments. --- tests/bugs/core_2966_test.py | 112 ++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/tests/bugs/core_2966_test.py b/tests/bugs/core_2966_test.py index 826849a9..a8a4213c 100644 --- a/tests/bugs/core_2966_test.py +++ b/tests/bugs/core_2966_test.py @@ -2,73 +2,89 @@ """ ID: issue-3348 -ISSUE: 3348 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/3348 TITLE: Wrong results or unexpected errors while sorting a large data set DESCRIPTION: JIRA: CORE-2966 FBTEST: bugs.core_2966 +NOTES: + [07.02.2025] pzotov + 1. Test runs for ~55-60s (checked on Win-10, Intel(R) Core(TM) i3 CPU 540 3.07GHz, FIREBIRD_TMP pointed to RAM drive. + 2. Test assumes that FIREBIRD_TMP points to the resource with enough space! + Otherwise it fails with one of following outcomes: + case-1 (if there is no folder that is specified in FIREBIRD_TMP): + INTERNALERROR> firebird.driver.types.DatabaseError: I/O error during "CreateFile (create)" operation for file "" + INTERNALERROR> -Error while trying to create file + INTERNALERROR> -- LOCALIZED message here + case-2 (if folder specified by FIREBIRD_TMP *exists* but no free space encountered during sort): + Statement failed, SQLSTATE = HY000 + sort error + -No free space found in temporary directories + -operating system directive WriteFile failed + - -- LOCALIZED message here + Because of presence of localized messages, we have to use 'io_enc = locale.getpreferredencoding()' in act.execute(). + Also, 'combine_output = True' must be used in order to see both STDOUT and STDERR in the same log. """ +import locale import pytest from firebird.qa import * -init_script = """create table t (col varchar(32000)); -commit; -set term !!; -execute block -as - declare variable i integer; -begin - i=0; - while (i < 200000) do begin - insert into t (col) values(mod(:i, 10)); - i= i+1; - end -end!! -set term ;!! -commit;""" +init_script = """ + create table t (col varchar(32000)); + commit; + set term ^; + execute block + as + declare variable i integer; + begin + i=0; + while (i < 200000) do begin + insert into t (col) values(mod(:i, 10)); + i= i+1; + end + end^ + set term ;^ + commit; +""" -db = db_factory(init=init_script) +db = db_factory(init = init_script) -test_script = """select col from t group by 1; -select cast(col as integer) from t group by 1; +test_script = """ + set list on; + select col as col_as_txt from t group by 1; + select cast(col as integer) as col_as_int from t group by 1; """ -act = isql_act('db', test_script, substitutions=[('=.*', '=')]) +substitutions = [('[ \t]+', ' '), ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ -COL -=============================================================================== -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 - - - CAST -============ - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - + COL_AS_TXT 0 + COL_AS_TXT 1 + COL_AS_TXT 2 + COL_AS_TXT 3 + COL_AS_TXT 4 + COL_AS_TXT 5 + COL_AS_TXT 6 + COL_AS_TXT 7 + COL_AS_TXT 8 + COL_AS_TXT 9 + COL_AS_INT 0 + COL_AS_INT 1 + COL_AS_INT 2 + COL_AS_INT 3 + COL_AS_INT 4 + COL_AS_INT 5 + COL_AS_INT 6 + COL_AS_INT 7 + COL_AS_INT 8 + COL_AS_INT 9 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From 42832104271e0ebf2226d3487ba69b3d9b51e697 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 13 Feb 2025 16:01:45 +0300 Subject: [PATCH 0371/1064] Added/Updated tests\bugs\gh_8434_test.py: Checked on 6.0.0.336. Currently only UTF8 is checked - see notes. --- tests/bugs/gh_8434_test.py | 371 +++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 tests/bugs/gh_8434_test.py diff --git a/tests/bugs/gh_8434_test.py b/tests/bugs/gh_8434_test.py new file mode 100644 index 00000000..328f8c56 --- /dev/null +++ b/tests/bugs/gh_8434_test.py @@ -0,0 +1,371 @@ +#coding:utf-8 + +""" +ID: issue-8434 +ISSUE: https://github.com/FirebirdSQL/firebird/pull/8434 +TITLE: Fix implicitly used collations after ALTER DOMAIN +DESCRIPTION: + Test creates two tables ('test1' and 'test2'), both are used to check non-ascii characters; results for Natural and Indexed Reads are verified. + First table is used to check output when 'common' indices are used, second - for check partial indices (and both tables have asc and desc indices). + Every table has text field based on UTF8-domain, initially no collation is specified for it. + Every table has four records with same character: 1) lowercased, with accent; 2) uppercased, with accent; 3) lowercased, "normal"; 4) uppercased, "normal". + First table stores character 'd', second - character 'l'. + We run query against each table with WHERE-expression like ' = ' -- where is in lowercased, "normal" form (i.e. 'd' or 'l'). + + When tables are in 'initial state' (i.e. before any domain altering) then such query must show only ONE record. + Then we change domain definition three times: + 1) 'alter domain ... collate unicode_ci'. + This must cause TWO records to be shown: 'lowercased, "normal"' and 'uppercased, "normal"'. Rows with accented chartacters must NOT be shown. + 2) 'alter domain ... collate unicode_ci_ai'. + This must cause ALL records to be shown, i.e. in "normal" form and with accent. + 3) 'alter domain', i.e. WITHOUT any 'collate' mention. + This must return output to what it was in 'initial state': only one record must be shown. +NOTES: + [13.02.2025] pzotov + ::: NB ::: + Currently only UTF8 charset is checked. + We can NOT check single-byte character sets because some of them have incompleted definitions of ACCENT-/CASE- INSENSITIVE rules. + + For example, in src/intl/collations/pw1251cyrr.h we can see than 'e' with accent characters are defined as a standalone primary code, + not with the same primary code as 'e' without accent. + This causes different comparison result of characters used in French, Russian and Ukrainian alphabets, namely: + 1) 'e' vs 'é' vs 'É' // U+0065; U+00E9; U+00C9 + 2) 'е' vs 'ё' vs 'Ё' // U+0435; U+0451; U+0401 + 3) 'г' vs 'ґ' vs 'Ґ' // U+0433; U+0491; U+0490 + Result for "1" will be true in all cases for ISO8859_1, but result for "2" and "3" will be true only when we compare accent_lower vs accent_upper. + + Explained by Adriano, letter 13.02.2025 13:44. + + Checked on 6.0.0.336. +""" +import sys +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError + +sys.stdout.reconfigure(encoding='utf-8') + +init_sql = """ + create domain dm_utf8 varchar(1) character set utf8; + + create table test1 ( + id int + ,what varchar(50) + ,f_utf8 dm_utf8 + ); + + create table test2 ( + id int + ,what varchar(50) + ,f_utf8 dm_utf8 + ); + + ---------------------- + insert into test1 ( + id + ,what + ,f_utf8 + ) + select + 1, 'lowered "D" w/accent', 'ð' from rdb$database union all select + 2, 'UPPERED "D" w/accent', 'Ð' from rdb$database union all select + 3, 'lowered "D" normal', 'd' from rdb$database union all select + 4, 'UPPERED "D" normal', 'D' from rdb$database + ; + + insert into test2 ( + id + ,what + ,f_utf8 + ) + select + 1, 'lowered "L" w/accent', 'ł' from rdb$database union all select + 2, 'UPPERED "L" w/accent', 'Ł' from rdb$database union all select + 3, 'lowered "L" normal', 'l' from rdb$database union all select + 4, 'UPPERED "L" normal', 'L' from rdb$database + ; + commit; + + -- ........................... + create index test1_asc on test1(f_utf8); + create descending index test1_dec on test1(f_utf8); + + create index test2_partial_asc on test2(f_utf8) where f_utf8 = 'l'; + create index test2_partial_dec on test2(f_utf8) where f_utf8 = 'l'; + commit; + + create view v1_chk_nr as select id, what, f_utf8 from test1 where f_utf8 || '' = 'd' order by id; + create view v1_chk_ir_asc as select id, what, f_utf8 from test1 where f_utf8 = 'd' order by f_utf8; + create view v1_chk_ir_dec as select id, what, f_utf8 from test1 where f_utf8 = 'd' order by f_utf8 desc; + + create view v2_chk_nr as select id, what, f_utf8 from test2 where f_utf8 || '' = 'l' order by id; + create view v2_chk_ir_asc as select id, what, f_utf8 from test2 where f_utf8 = 'l' order by f_utf8; + create view v2_chk_ir_dec as select id, what, f_utf8 from test2 where f_utf8 = 'l' order by f_utf8 desc; + commit; +""" + +db = db_factory(init = init_sql) +act = python_act('db', substitutions = [(r'record length: \d+, key length: \d+', 'record length: NN, key length: MM')]) + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- + +@pytest.mark.version('>=6') +def test_1(act: Action, capsys): + qry_map = { + 1 : 'select * from v1_chk_nr' + ,2 : 'select * from v1_chk_ir_asc' + ,3 : 'select * from v1_chk_ir_dec' + ,4 : 'select * from v2_chk_nr' + ,5 : 'select * from v2_chk_ir_asc' + ,6 : 'select * from v2_chk_ir_dec' + } + + alter_lst = ( + '' + ,'alter domain dm_utf8 type varchar(1) character set utf8 collate unicode_ci' + ,'alter domain dm_utf8 type varchar(1) character set utf8 collate unicode_ci_ai' + ,'alter domain dm_utf8 type varchar(1) character set utf8' + ) + + with act.db.connect(charset = 'utf8') as con: + cur = con.cursor() + for alter_i in alter_lst: + if alter_i.strip(): + con.execute_immediate(alter_i) + con.commit() + print(f'\nAfter {alter_i}:') + else: + print('Initial state:') + + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) + + print('Query:', v) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + print('') + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + print(r[0], r[1]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + + expected_stdout = """ + Initial state: + + Query: select * from v1_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST1" as "V1_CHK_NR TEST1" Full Scan + 3 lowered "D" normal + Query: select * from v1_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_ASC TEST1" Access By ID + ............-> Index "TEST1_ASC" Range Scan (full match) + 3 lowered "D" normal + Query: select * from v1_chk_ir_dec + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_DEC TEST1" Access By ID + ............-> Index "TEST1_DEC" Range Scan (full match) + 3 lowered "D" normal + Query: select * from v2_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_NR TEST2" Full Scan + 3 lowered "L" normal + Query: select * from v2_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST2" as "V2_CHK_IR_ASC TEST2" Access By ID + ............-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + Query: select * from v2_chk_ir_dec + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_IR_DEC TEST2" Access By ID + ................-> Bitmap + ....................-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + + + After alter domain dm_utf8 type varchar(1) character set utf8 collate unicode_ci: + + Query: select * from v1_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST1" as "V1_CHK_NR TEST1" Full Scan + 3 lowered "D" normal + 4 UPPERED "D" normal + Query: select * from v1_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_ASC TEST1" Access By ID + ............-> Index "TEST1_ASC" Range Scan (full match) + 3 lowered "D" normal + 4 UPPERED "D" normal + Query: select * from v1_chk_ir_dec + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_DEC TEST1" Access By ID + ............-> Index "TEST1_DEC" Range Scan (full match) + 4 UPPERED "D" normal + 3 lowered "D" normal + Query: select * from v2_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_NR TEST2" Full Scan + 3 lowered "L" normal + 4 UPPERED "L" normal + Query: select * from v2_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST2" as "V2_CHK_IR_ASC TEST2" Access By ID + ............-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + 4 UPPERED "L" normal + Query: select * from v2_chk_ir_dec + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_IR_DEC TEST2" Access By ID + ................-> Bitmap + ....................-> Index "TEST2_PARTIAL_ASC" Full Scan + 4 UPPERED "L" normal + 3 lowered "L" normal + + + After alter domain dm_utf8 type varchar(1) character set utf8 collate unicode_ci_ai: + + Query: select * from v1_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST1" as "V1_CHK_NR TEST1" Full Scan + 1 lowered "D" w/accent + 2 UPPERED "D" w/accent + 3 lowered "D" normal + 4 UPPERED "D" normal + Query: select * from v1_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_ASC TEST1" Access By ID + ............-> Index "TEST1_ASC" Range Scan (full match) + 3 lowered "D" normal + 4 UPPERED "D" normal + 1 lowered "D" w/accent + 2 UPPERED "D" w/accent + Query: select * from v1_chk_ir_dec + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_DEC TEST1" Access By ID + ............-> Index "TEST1_DEC" Range Scan (full match) + 2 UPPERED "D" w/accent + 1 lowered "D" w/accent + 4 UPPERED "D" normal + 3 lowered "D" normal + Query: select * from v2_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_NR TEST2" Full Scan + 1 lowered "L" w/accent + 2 UPPERED "L" w/accent + 3 lowered "L" normal + 4 UPPERED "L" normal + Query: select * from v2_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST2" as "V2_CHK_IR_ASC TEST2" Access By ID + ............-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + 4 UPPERED "L" normal + 1 lowered "L" w/accent + 2 UPPERED "L" w/accent + Query: select * from v2_chk_ir_dec + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_IR_DEC TEST2" Access By ID + ................-> Bitmap + ....................-> Index "TEST2_PARTIAL_ASC" Full Scan + 2 UPPERED "L" w/accent + 1 lowered "L" w/accent + 4 UPPERED "L" normal + 3 lowered "L" normal + + + After alter domain dm_utf8 type varchar(1) character set utf8: + + Query: select * from v1_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST1" as "V1_CHK_NR TEST1" Full Scan + 3 lowered "D" normal + Query: select * from v1_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_ASC TEST1" Access By ID + ............-> Index "TEST1_ASC" Range Scan (full match) + 3 lowered "D" normal + Query: select * from v1_chk_ir_dec + Select Expression + ....-> Filter + ........-> Table "TEST1" as "V1_CHK_IR_DEC TEST1" Access By ID + ............-> Index "TEST1_DEC" Range Scan (full match) + 3 lowered "D" normal + Query: select * from v2_chk_nr + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_NR TEST2" Full Scan + 3 lowered "L" normal + Query: select * from v2_chk_ir_asc + Select Expression + ....-> Filter + ........-> Table "TEST2" as "V2_CHK_IR_ASC TEST2" Access By ID + ............-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + Query: select * from v2_chk_ir_dec + Select Expression + ....-> Sort (record length: NN, key length: MM) + ........-> Filter + ............-> Table "TEST2" as "V2_CHK_IR_DEC TEST2" Access By ID + ................-> Bitmap + ....................-> Index "TEST2_PARTIAL_ASC" Full Scan + 3 lowered "L" normal + """ + + act.expected_stdout = expected_stdout + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 07e6f78172b6c0ca1e5743ecf2e37b601d9c88f2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 02:25:53 +0300 Subject: [PATCH 0372/1064] Added aliases needed for test #8429 --- files/qa-databases.conf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index b5d90b1a..5209df51 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -286,6 +286,22 @@ tmp_gh_8391_alias = $(dir_sampleDb)/qa/tmp_gh_8391.fdb DefaultDbCachePages = 128 } + +gh_8429_alias_a = $(dir_sampleDb)/qa/tmp_gh_8429_a.fdb +{ + KeyHolderPlugin = KH2 +} + +gh_8429_alias_b = $(dir_sampleDb)/qa/tmp_gh_8429_b.fdb +{ + KeyHolderPlugin = KH2 +} + +gh_8429_alias_c = $(dir_sampleDb)/qa/tmp_gh_8429_c.fdb +{ + KeyHolderPlugin = KH2 +} + # Databases for replication tests: # db_main_alias = $(dir_sampleDb)/qa_replication/db_main.fdb From cca2dfcdc36c5f58fd59e24359435efd46d46153 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 02:26:14 +0300 Subject: [PATCH 0373/1064] Added/Updated tests\bugs\gh_8429_test.py: Checked on 6.0.0.607-1985b88; 5.0.2.1610-5e63ad0; 4.0.6.3185-9cac45a - all fine. See notes. --- tests/bugs/gh_8429_test.py | 295 +++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 tests/bugs/gh_8429_test.py diff --git a/tests/bugs/gh_8429_test.py b/tests/bugs/gh_8429_test.py new file mode 100644 index 00000000..415389ec --- /dev/null +++ b/tests/bugs/gh_8429_test.py @@ -0,0 +1,295 @@ +#coding:utf-8 + +""" +ID: issue-8429 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8429 +TITLE: Segfault when already destroyed callback interface is used +DESCRIPTION: + Test uses THREE preliminary created aliases with KeyHolderPlugin that points to special configuration with name 'KH2'. + This configuration makes crypt plugin accept key ONLY from client app (in contrary to other encryption-related tests). + Three non-privileged users are created for this test. +NOTES: + [24.02.2025] pzotov + 1) firebird.conf must have KeyHolderPlugin = fbSampleKeyHolder and plugins/fbSampleKeyHolder.conf must have Auto = true. + 2) aliases gh_8429_alias_a, gh_8429_alias_b, gh_8429_alias_c that are used in this test must have (in databases.conf) + KeyHolderPlugin = KH2 and plugins.conf must contain: + --------------- + Plugin = KH2 { + Module = $(dir_plugins)/fbSampleKeyHolder + RegisterName = fbSampleKeyHolder + Config = KH2 + } + Config = KH2 { + Auto = false + } + --------------- + + 3) Third database (defined by 'gh_8429_alias_c') must be encrypted in FB-6.x in order to reproduce bug. + 4) All databases are created here by explicit 'create_database()' call and their deletion does NOT perform. + This was done intentionally in order to suppress appearance of any encryption-related errors that do not matter. + + Great thanks to Alex for provided scenario for this test (letter 10-feb-2025 20:43) ans lot of suggestions. + + Confirmed bug only for Super, snapshots: 6.0.0.600-188de60; 5.0.2.1606-a92f352; 4.0.6.3181-00b648f. + Classic not affected. + Checked on 6.0.0.607-1985b88; 5.0.2.1610-5e63ad0; 4.0.6.3185-9cac45a - all fine. +""" +import os +import time +import datetime as py_dt +import re +from pathlib import Path + +import pytest +from firebird.qa import * +from firebird.driver import create_database, ShutdownMode, ShutdownMethod + +########################### +### S E T T I N G S ### +########################### + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +enc_settings = QA_GLOBALS['encryption'] + +# ACHTUNG: this must be carefully tuned on every new host: +# +MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN' if os.name == 'nt' else 'MAX_WAIT_FOR_ENCR_FINISH_NIX']) +assert MAX_WAITING_ENCR_FINISH > 0 + +ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt + +db = db_factory() +usr_x = user_factory('db', name = 'tmp_8429_x', password = 'tmp_8429_x', plugin = 'Srp') +usr_y = user_factory('db', name = 'tmp_8429_y', password = 'tmp_8429_y', plugin = 'Srp') +usr_z = user_factory('db', name = 'tmp_8429_z', password = 'tmp_8429_z', plugin = 'Srp') + +db_a = db_factory(filename = '#gh_8429_alias_a', do_not_create = True, do_not_drop = True) +db_b = db_factory(filename = '#gh_8429_alias_b', do_not_create = True, do_not_drop = True) +db_c = db_factory(filename = '#gh_8429_alias_c', do_not_create = True, do_not_drop = True) + +act_a = python_act('db_a') +act_b = python_act('db_b') +act_c = python_act('db_c') + +#---------------------------------------------------- + +def get_filename_by_alias(act: Action, alias_from_dbconf = None): + + if not alias_from_dbconf: + alias_from_dbconf = act.db.db_path + + # Scan line-by-line through databases.conf, find line starting with and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + alias_from_dbconf + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_6147_alias = $(dir_sampleDb)/qa/tmp_core_6147.fdb + # - then we extract filename: 'tmp_core_6147.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + #------------------------------------------------------------------ + # Full path + filename of database to which we will try to connect: + # + tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) + + return tmp_fdb + +#----------------------------------------------------------------------- + +def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): + if mode == 'encrypt': + # See letter from Alex, 15.12.2023 16:16 demo-plugin can not transfer named key over network. + # Because of that, we have to use 'ALTER DATABASE ENCRYPT WITH ' _WITHOUT_ adding 'key "{ENCRYPTION_KEY}"'. + # ::: NB ::: One need to be sure that $FB_HOME/plugins.conf contains following lines: + # Plugin = KH2 { + # Module = $(dir_plugins)/fbSampleKeyHolder + # RegisterName = fbSampleKeyHolder + # Config = KH2 + # } + # Config = KH2 { + # Auto = false + # } + # Otherwise error will raise: + # unsuccessful metadata update + # -ALTER DATABASE failed + # -Missing database encryption key for your attachment + # -Plugin fbSampleDbCrypt: + # -Crypt key not set + # + alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}"' # <<< ::: NB ::: DO NOT add '... key "{ENCRYPTION_KEY}"' here! + wait_for_state = 'Database encrypted' + elif mode == 'decrypt': + alter_db_sttm = 'alter database decrypt' + wait_for_state = 'Database not encrypted' + + + e_thread_finished = False + + # 0 = non crypted; + # 1 = has been encrypted; + # 2 = is DEcrypting; + # 3 = is Encrypting; + # + REQUIRED_CRYPT_STATE = 1 if mode == 'encrypt' else 0 + current_crypt_state = -1 + d1 = py_dt.timedelta(0) + with act.db.connect() as con: + cur = con.cursor() + ps, rs = None, None + try: + ps = cur.prepare('select mon$crypt_state from mon$database') + t1=py_dt.datetime.now() + d1 = t1-t1 + con.execute_immediate(alter_db_sttm) + con.commit() + while True: + t2=py_dt.datetime.now() + d1=t2-t1 + if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: + break + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + ###################################################### + ### C H E C K M O N $ C R Y P T _ S T A T E ### + ###################################################### + current_crypt_state = r[0] + con.commit() + if current_crypt_state == REQUIRED_CRYPT_STATE: + e_thread_finished = True + break + else: + time.sleep(0.5) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + + assert e_thread_finished, f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms; current_crypt_state={current_crypt_state}' + + +#----------------------------------------------------------------------- + +@pytest.mark.es_eds +@pytest.mark.encryption +@pytest.mark.version('>=4.0.6') +def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User, usr_z: User, capsys): + + dbfile_a = get_filename_by_alias(act_a) + dbfile_b = get_filename_by_alias(act_b) + dbfile_c = get_filename_by_alias(act_c) + + dbfile_a.unlink(missing_ok = True) + dbfile_b.unlink(missing_ok = True) + dbfile_c.unlink(missing_ok = True) + + with create_database(act_a.db.db_path, user = act_a.db.user, password = act_a.db.password) as con_a, \ + create_database(act_b.db.db_path, user = act_b.db.user, password = act_b.db.password) as con_b, \ + create_database(act_c.db.db_path, user = act_c.db.user, password = act_c.db.password) as con_c: + + sql = f""" + create procedure sp_a (a_who varchar(31)) returns (o_info varchar(512)) as + begin + -- e1-meta.sql: + execute statement 'select * from sp_b(''' || a_who || ''')' as user '{usr_x.name}' password '{usr_x.password}' on external 'gh_8429_alias_b' into o_info; + suspend; + end + ^ + grant execute on procedure sp_a to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_a.execute_immediate(s) + con_a.commit() + + # .................................................. + + sql = f""" + create procedure sp_b (a_who varchar(31)) returns (o_info varchar(512)) as + begin + execute statement 'select * from sp_c' as user a_who password a_who on external 'gh_8429_alias_c' into o_info; + suspend; + end + ^ + grant execute on procedure sp_b to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_b.execute_immediate(s) + con_b.commit() + + # .................................................. + + sql = f""" + create procedure sp_c returns (o_info varchar(512)) as + begin + o_info = lower(current_user); + -- o_info = lower(rdb$get_context('SYSTEM', 'DB_NAME')) || ':' || lower(current_user); + suspend; + end + ^ + grant execute on procedure sp_c to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_c.execute_immediate(s) + con_c.commit() + + ############################################ + ### E N C R Y P T D A T A B A S E ### + ############################################ + run_encr_decr(act_c, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys) + + # .................................................. + + + with act_a.db.connect() as con_a: + cur = con_a.cursor() + cur.execute(f"select o_info from sp_a('{usr_x.name.lower()}')") + for r in cur: + print(r[0]) + + with act_a.db.connect() as con_a: + cur = con_a.cursor() + cur.execute(f"select o_info from sp_a('{usr_y.name.lower()}')") + for r in cur: + print(r[0]) + + act_a.expected_stdout = f""" + {usr_x.name.lower()} + {usr_y.name.lower()} + """ + act_a.stdout = capsys.readouterr().out + assert act_a.clean_stdout == act_a.clean_expected_stdout + act_a.reset() From 8cd5544bd9088e8d82012039f830e94c6c281d0d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 16:58:50 +0300 Subject: [PATCH 0374/1064] Added/Updated tests\bugs\gh_8057_test.py: Changed offset calculations according to #93db88: ODS14: header page refactoring (#8401) --- tests/bugs/gh_8057_test.py | 77 +++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/tests/bugs/gh_8057_test.py b/tests/bugs/gh_8057_test.py index c1a797e9..c6a53c50 100644 --- a/tests/bugs/gh_8057_test.py +++ b/tests/bugs/gh_8057_test.py @@ -55,6 +55,10 @@ Checked on 6.0.0.295-ef66a9b (22-mar-2024 13:48): all OK,every of checked system tables has non-zero statistics for its indices. Test executiuon time: ~8...10 seconds. + [24.02.2025] + Changed offset calculations according to #93db88: ODS14: header page refactoring (#8401) + See: https://github.com/FirebirdSQL/firebird/commit/93db88084d5a04aaa3f98179e76cdfa092431fa8 + Thanks to Vlad for explanations. """ import sys @@ -260,6 +264,47 @@ def parse_index_root_page(db_file, pg_size, rel_name, irt_page_number, rel_sel_m # https://firebirdsql.org/file/documentation/html/en/firebirddocs/firebirdinternals/firebird-internals.html#fbint-page-6 # https://docs.python.org/3/library/struct.html#format-characters + """ + See src/jrd/ods.h, https://github.com/FirebirdSQL/firebird/pull/8340 + *** BEFORE *** + struct index_root_page + { + pag irt_header; + USHORT irt_relation; + USHORT irt_count; + struct irt_repeat { + SLONG irt_root; + union { + float irt_selectivity; + SLONG irt_transaction; + } irt_stuff; + USHORT irt_desc; + UCHAR irt_keys; + UCHAR irt_flags; + } irt_rpt[1]; + }; + + *** AFTER *** + struct index_root_page + { + pag irt_header; + USHORT irt_relation; // 2 relation id (for consistency) + USHORT irt_count; // 2 number of indices + ULONG irt_dummy; // 4 so far used as a padding to ensure the same alignment in 32-bit and 64-bit builds + struct irt_repeat + { + FB_UINT64 irt_transaction; // 8 transaction in progress + ULONG irt_page_num; // 4 page number + ULONG irt_page_space_id; // 4 page space + USHORT irt_desc; // 2 offset to key descriptions + USHORT irt_flags; // 2 index flags + UCHAR irt_state; // 1 index state + UCHAR irt_keys; // 1 number of keys in index + USHORT irt_dummy; // 2 alignment to 8-byte boundary + } irt_rpt[1]; + }; + + """ # Two bytes, UNsigned. Offset 0x10 on the page. The relation id. This is the value of RDB$RELATIONS.RDB$RELATION_ID. irt_relation = struct.unpack_from('@H', page_content[0x10:0x12])[0] # (128,) --> 128 @@ -267,25 +312,37 @@ def parse_index_root_page(db_file, pg_size, rel_name, irt_page_number, rel_sel_m # Two bytes, UNsigned. Offset 0x12 on the page. The number of indices defined for this table. irt_count = struct.unpack_from('@H', page_content[0x12:0x14])[0] + # 24.02.2025 + irt_dummy = struct.unpack_from('@H', page_content[0x14:0x18])[0] + if verbose: print(f'{irt_relation=}, {rel_name.strip()=}, {irt_count=}') for i in range(irt_count): - # 4+4+2+1+1 = 12 - irt_root_offset_i = i * 12 + int(0x14) - irt_tran_offset_i = i * 12 + int(0x18) - irt_desc_offset_i = i * 12 + int(0x1c) - irt_keys_offset_i = i * 12 + int(0x1e) - irt_flags_offset_i = i * 12 + int(0x1f) + ################### + IRT_REPEAT_LEN = 24 + ################### + + irt_tran_offset_i = i * IRT_REPEAT_LEN + int(0x18) + irt_page_num_offset = i * IRT_REPEAT_LEN + int(0x26) # 18 + 8 + irt_page_space_id_offset = i * IRT_REPEAT_LEN + int(0x30) # 26 + 4 + irt_desc_offset_i = i * IRT_REPEAT_LEN + int(0x34) # 30 + 4 + irt_flags_offset_i = i * IRT_REPEAT_LEN + int(0x36) # 34 + 2 + irt_state_offset_i = i * IRT_REPEAT_LEN + int(0x38) # 36 + 2 + irt_keys_offset_i = i * IRT_REPEAT_LEN + int(0x39) # 38 + 1 + irt_dummy_offset = i * IRT_REPEAT_LEN + int(0x40) # 39 + 1 + # Four bytes, SIGNED. Offset 0x00 in each descriptor array entry. # This field is the page number where the root page for the individual index (page type 0x07) is located. - irt_root_i = struct.unpack_from('@i', page_content[irt_root_offset_i : irt_root_offset_i + 4])[0] + # 24.02.2025: this field no more exists in new ODS: + irt_root_i = -1 # before 24.02.2025: struct.unpack_from('@i', page_content[irt_root_offset_i : irt_root_offset_i + 4])[0] - # Four bytes, SIGNED. Offset 0x04 in each descriptor array entry. # Normally this field will be zero but if an index is in the process of being created, the transaction id will be found here. - irt_tran_i = struct.unpack_from('@i', page_content[irt_tran_offset_i : irt_tran_offset_i + 4])[0] + # irt_tran_i = struct.unpack_from('@i', page_content[irt_tran_offset_i : irt_tran_offset_i + 4])[0] + # 24.02.2025: this field now is FB_UINT64, i.e 8 bytes: + irt_tran_i = struct.unpack_from('@i', page_content[irt_tran_offset_i : irt_tran_offset_i + 8])[0] # Two bytes, UNsigned. Offset 0x08 in each descriptor array entry. This field holds the offset, from the start of the page, # to the index field descriptors which are located at the bottom end (ie, highest addresses) of the page. @@ -310,7 +367,7 @@ def parse_index_root_page(db_file, pg_size, rel_name, irt_page_number, rel_sel_m print(f' {i=} ::: {irt_root_i=}, {irt_tran_i=}, {irt_desc_i=}, {irt_keys_i=}, {irt_flags_i=}, bin(irt_flags_i)=','{0:08b}'.format(irt_flags_i)) for j in range(irt_keys_i): - # 2+2+4 = 8 + # Two bytes, UNsigned. Offset 0x00 in each field descriptor. This field defines the field number of the table that makes up 'this' field in the index. # This number is equivalent to RDB$RELATION_FIELDS.RDB$FIELD_ID. irtd_field = struct.unpack_from('@H', page_content[ j*8 + irt_desc_i : j*8 + irt_desc_i + 2])[0] From 9efd75bf809153248ddd21e4b62d5f76f1cae70d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 17:35:45 +0300 Subject: [PATCH 0375/1064] Added/Updated tests\bugs\gh_8437_test.py: Checked on 6.0.0.652-226622f; 5.0.3.1622-c1a518f; 4.0.6.3189-3fb0bbf - all fine. --- tests/bugs/gh_8437_test.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/bugs/gh_8437_test.py diff --git a/tests/bugs/gh_8437_test.py b/tests/bugs/gh_8437_test.py new file mode 100644 index 00000000..2eec3984 --- /dev/null +++ b/tests/bugs/gh_8437_test.py @@ -0,0 +1,35 @@ +#coding:utf-8 + +""" +ID: issue-8437 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8437 +TITLE: Segmentation fault when running query with partition by and subquery +DESCRIPTION: +NOTES: + [24.02.2025] pzotov + Confirmed bug on 6.0.0.647-9fccb55; 5.0.3.1619-81c5f17; 4.0.6.3188-8ee1ca8 + Checked on 6.0.0.652-226622f; 5.0.3.1622-c1a518f; 4.0.6.3189-3fb0bbf - all fine. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set heading off; + select row_number()over(partition by (select 1 from rdb$database)) from rdb$database; +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + 1 +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From 95bcd0f9c429824099eb27abee230634b7da0eec Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 19:02:55 +0300 Subject: [PATCH 0376/1064] Added/Updated tests\bugs\gh_8278_test.py: Checked on intermediate snapshots: 6.0.0.652-58633c8; 5.0.3.1622-22d23c1 --- tests/bugs/gh_8278_test.py | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/bugs/gh_8278_test.py diff --git a/tests/bugs/gh_8278_test.py b/tests/bugs/gh_8278_test.py new file mode 100644 index 00000000..7cc12bdf --- /dev/null +++ b/tests/bugs/gh_8278_test.py @@ -0,0 +1,98 @@ +#coding:utf-8 + +""" +ID: issue-8278 +ISSUE: 8278 +TITLE: Avoid index lookup for a NULL key if the condition is known to always be FALSE in this case +DESCRIPTION: Test uses ticket example but with reduced number of records that will be inserted into tables. + Number of fetches is compared with MAX_FETCHES_ALERT. After fix trace shows that it is ~5600. +NOTES: + [24.01.2025] pzotov + Commits that fixed problem: + 6.x: https://github.com/FirebirdSQL/firebird/commit/58633c81ea490326d880f42780bb7f293c2a0ae8 + 5.x: https://github.com/FirebirdSQL/firebird/commit/22d23c17d94e390f4ca058afff6ac0338d014225 + + Confirmed problem on 6.0.0.647-9fccb55. + Checked on intermediate snapshots: 6.0.0.652-58633c8; 5.0.3.1622-22d23c1 +""" + +from pathlib import Path + +import pytest +from firebird.qa import * +from firebird.driver import DatabaseError + +T1_COUNT = 30000 +T2_COUNT = 100 +T3_COUNT = 10 +MAX_FETCHES_ALERT = 6000 + +init_sql = f""" + recreate table t1 (t1_id int not null); + recreate table t2 (t2_id int not null, t1_id int); + recreate table t3 (t3_id int not null, t1_id int); + + set term ^; + execute block as + declare l_t1_id int; + declare l_t2_id int; + declare l_t3_id int; + declare n1 int = {T1_COUNT}; + declare n2 int = {T2_COUNT}; + declare n3 int = {T3_COUNT}; + begin + l_t3_id = 1; + while (l_t3_id <= n1) do + begin + l_t1_id = iif(mod(l_t3_id, n2) = 0, trunc(l_t3_id/n2), null); + l_t2_id = iif(mod(l_t3_id, n3) = 0, trunc(l_t3_id/n3), null); + + if (l_t1_id is not null) then + insert into t1 (t1_id) values (:l_t1_id); + + insert into t3 (t3_id, t1_id) values (:l_t3_id, :l_t1_id); + + if (l_t2_id is not null) then + insert into t2 (t2_id, t1_id) values (:l_t2_id, :l_t1_id); + + l_t3_id = l_t3_id + 1; + end + end + ^ + set term ;^ + commit; + + alter table t1 add constraint t1_pk primary key (t1_id); + alter table t2 add constraint t2_pk primary key (t2_id); + alter table t3 add constraint t3_pk primary key (t3_id); + alter table t2 add constraint t2_fk foreign key (t1_id) references t1 (t1_id); + alter table t3 add constraint t3_fk foreign key (t1_id) references t1 (t1_id); + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db') + +@pytest.mark.version('>=5.0.3') +def test_1(act: Action, capsys): + + expected_msg = 'Number of fetches: EXPECTED' + with act.db.connect() as con: + cur = con.cursor() + test_sql = """ + select count(*) /* trace_me */ + from t2 + left outer join t1 on t1.t1_id = t2.t1_id + left outer join t3 on t3.t1_id = t1.t1_id + """ + + fetches_ini = con.info.fetches + cur.execute(test_sql) + cur.fetchall() + sql_fetches = con.info.fetches - fetches_ini + print(expected_msg if sql_fetches <= MAX_FETCHES_ALERT else f'Number of fetches UNEXPECTED: {sql_fetches} - greater than {MAX_FETCHES_ALERT}' ) + + act.expected_stdout = f""" + {expected_msg} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 5899c3a2b8a03a35a2ae72d6e44233d4dce1d09f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 24 Feb 2025 22:20:01 +0300 Subject: [PATCH 0377/1064] Added/Updated tests\bugs\gh_8421_test.py: Checked on intermediate snapshot: 6.0.0.652-58633c8. --- tests/bugs/gh_8421_test.py | 329 +++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 tests/bugs/gh_8421_test.py diff --git a/tests/bugs/gh_8421_test.py b/tests/bugs/gh_8421_test.py new file mode 100644 index 00000000..00a6be49 --- /dev/null +++ b/tests/bugs/gh_8421_test.py @@ -0,0 +1,329 @@ +#coding:utf-8 + +""" +ID: issue-8421 +ISSUE: 8421 +TITLE: Add pointers tree to TempSpace class +DESCRIPTION: + Test uses example provided in the ticket, but with different set of N values. + Following results were achieved for set of N values provided in the ticket: + --------------------------------------------------- + BEFORE FIX AFTER FIX + N time_ms ratio N time_ms ratio + --------------------------------------------------- + 1000 218 | 1000 213 + 2000 627 2.88 | 2000 503 2.36 + 4000 1493 2.38 | 4000 997 1.98 + 8000 3835 2.57 | 8000 2157 2.16 + 16000 14922 3.89 | 16000 4271 1.98 + 32000 67525 4.53 | 32000 8697 2.04 + 64000 253474 3.75 | 64000 17013 1.96 + 128000 1007229 3.97 | 128000 35285 2.07 + --------------------------------------------------- + + For N = 375; 750; 1500; 3000; 6000; 12000; 24000; 48000: + * BEFORE fix: + poor_ratios = [2.324675324675325, 2.2960893854748603, 2.411192214111922, 2.4339051463168517, 3.16832504145937, 4.301753467678618, 4.9132749285149355] + stdev(poor_ratios) = 1.0723186770194812 + + * AFTER fix: + good_ratios = [2.0357142857142856, 2.08187134502924, 1.9438202247191012, 2.066473988439306, 1.9713286713286713, 2.0503724725079815, 2.0278546712802767] + stdev(good_ratios) = 0.05031744060704646 +NOTES: + [24.01.2025] pzotov + Commit that fixed problem: + 6.x: https://github.com/FirebirdSQL/firebird/commit/8d6c46e0e1f8eec374008e5ded6be119264ed3a6 + + Test executes for ~30s. + Confirmed problem on 6.0.0.647-9fccb55. + Checked on intermediate snapshot: 6.0.0.652-58633c8. +""" + +from statistics import stdev +import time +import datetime as py_dt + +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db') + +################# +MAX_STD_DEV = 0.5 +################# + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + ddl_lst = [] + ddl_lst.extend( + ( + """ + recreate table log_table( + log_id bigint generated by default as identity constraint pk_log_table primary key + ,field_name varchar(31) not null + ,old_value blob + ) + """ + ,""" + recreate table test_table ( + id bigint not null, + fld_01 varchar(40), + fld_02 date, + fld_03 varchar(40), + fld_04 date, + fld_05 varchar(1000), + fld_06 varchar(1000), + fld_07 numeric(15,2), + fld_08 date, + fld_09 varchar(95), + fld_10 bigint, + fld_11 bigint, + fld_12 bigint, + fld_13 varchar(250), + fld_14 bigint, + fld_15 date, + fld_16 integer, + fld_17 bigint, + fld_18 date, + fld_19 bigint, + fld_20 varchar(95), + fld_21 date, + fld_22 bigint, + fld_23 numeric(16,0), + fld_24 smallint, + fld_25 bigint, + fld_26 bigint, + fld_27 smallint default 0, + fld_28 date, + fld_29 smallint, + fld_30 date, + fld_31 date, + fld_32 date, + fld_33 date, + fld_34 date, + fld_35 date, + fld_36 date, + fld_37 date, + fld_38 date, + fld_39 date, + fld_40 smallint, + fld_41 smallint, + fld_42 smallint, + fld_43 bigint, + fld_44 bigint, + fld_45 bigint, + fld_46 smallint, + fld_47 varchar(1000), + fld_48 bigint, + fld_49 varchar(4000), + fld_50 bigint + ) + """ + ,'create generator audit' + ,'alter table test_table add constraint pk_test_table primary key (id) using descending index pk_test_table' + ,""" + create or alter trigger h$test_table for test_table + active after update position 0 + as + declare id bigint; + declare o blob sub_type 1 segment size 80; + begin + id = gen_id(audit, 1); + o = old.fld_01; if (o is distinct from new.fld_01) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_01', :o); end + o = old.fld_02; if (o is distinct from new.fld_02) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_02', :o); end + o = old.fld_03; if (o is distinct from new.fld_03) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_03', :o); end + o = old.fld_04; if (o is distinct from new.fld_04) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_04', :o); end + o = old.fld_05; if (o is distinct from new.fld_05) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_05', :o); end + o = old.fld_06; if (o is distinct from new.fld_06) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_06', :o); end + o = old.fld_07; if (o is distinct from new.fld_07) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_07', :o); end + o = old.fld_08; if (o is distinct from new.fld_08) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_08', :o); end + o = old.fld_09; if (o is distinct from new.fld_09) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_09', :o); end + o = old.fld_10; if (o is distinct from new.fld_10) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_10', :o); end + + + o = old.fld_11; if (o is distinct from new.fld_11) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_11', :o); end + o = old.fld_12; if (o is distinct from new.fld_12) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_12', :o); end + o = old.fld_13; if (o is distinct from new.fld_13) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_13', :o); end + o = old.fld_14; if (o is distinct from new.fld_14) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_14', :o); end + o = old.fld_15; if (o is distinct from new.fld_15) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_15', :o); end + o = old.fld_16; if (o is distinct from new.fld_16) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_16', :o); end + o = old.fld_17; if (o is distinct from new.fld_17) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_17', :o); end + o = old.fld_18; if (o is distinct from new.fld_18) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_18', :o); end + o = old.fld_19; if (o is distinct from new.fld_19) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_19', :o); end + o = old.fld_20; if (o is distinct from new.fld_20) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_20', :o); end + + + o = old.fld_21; if (o is distinct from new.fld_21) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_21', :o); end + o = old.fld_22; if (o is distinct from new.fld_22) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_22', :o); end + o = old.fld_23; if (o is distinct from new.fld_23) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_23', :o); end + o = old.fld_24; if (o is distinct from new.fld_24) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_24', :o); end + o = old.fld_25; if (o is distinct from new.fld_25) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_25', :o); end + o = old.fld_26; if (o is distinct from new.fld_26) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_26', :o); end + o = old.fld_27; if (o is distinct from new.fld_27) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_27', :o); end + o = old.fld_28; if (o is distinct from new.fld_28) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_28', :o); end + o = old.fld_29; if (o is distinct from new.fld_29) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_29', :o); end + o = old.fld_30; if (o is distinct from new.fld_30) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_30', :o); end + + + o = old.fld_31; if (o is distinct from new.fld_31) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_31', :o); end + o = old.fld_32; if (o is distinct from new.fld_32) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_32', :o); end + o = old.fld_33; if (o is distinct from new.fld_33) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_33', :o); end + o = old.fld_34; if (o is distinct from new.fld_34) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_34', :o); end + o = old.fld_35; if (o is distinct from new.fld_35) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_35', :o); end + o = old.fld_36; if (o is distinct from new.fld_36) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_36', :o); end + o = old.fld_37; if (o is distinct from new.fld_37) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_37', :o); end + o = old.fld_38; if (o is distinct from new.fld_38) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_38', :o); end + o = old.fld_39; if (o is distinct from new.fld_39) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_39', :o); end + o = old.fld_40; if (o is distinct from new.fld_40) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_40', :o); end + + + + o = old.fld_41; if (o is distinct from new.fld_41) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_41', :o); end + o = old.fld_42; if (o is distinct from new.fld_42) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_42', :o); end + o = old.fld_43; if (o is distinct from new.fld_43) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_43', :o); end + o = old.fld_44; if (o is distinct from new.fld_44) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_44', :o); end + o = old.fld_45; if (o is distinct from new.fld_45) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_45', :o); end + o = old.fld_46; if (o is distinct from new.fld_46) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_46', :o); end + o = old.fld_47; if (o is distinct from new.fld_47) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_47', :o); end + o = old.fld_48; if (o is distinct from new.fld_48) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_48', :o); end + o = old.fld_49; if (o is distinct from new.fld_49) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_49', :o); end + o = old.fld_50; if (o is distinct from new.fld_50) then begin insert into log_table(log_id, field_name, old_value) values(:id, 'fld_50', :o); end + end + """ + ,""" + execute block + as + declare id bigint; + begin + id = 0; + while (id < 128000) do + begin + insert into test_table (id,fld_01,fld_02,fld_03,fld_04,fld_05,fld_06,fld_07,fld_08,fld_09,fld_10,fld_11,fld_12,fld_13,fld_14,fld_15,fld_16,fld_17,fld_18,fld_19,fld_20,fld_21,fld_22,fld_23,fld_24,fld_25,fld_26,fld_27,fld_28,fld_29,fld_30,fld_31,fld_32,fld_33,fld_34,fld_35,fld_36,fld_37,fld_38,fld_39,fld_40,fld_41,fld_42,fld_43,fld_44,fld_45,fld_46,fld_47,fld_48,fld_49,fld_50) + values ( + :id, + 'Identifier', + '2025-01-23', + '1234567890123456789', + '2025-01-23', + 'Test data', + 'Test another data', + 500, + '2025-01-24', + 'Test Test Test', + 3, + 12345678901234, + 12, + 'Test', + 12345678901234, + '2025-01-30', + 0, + NULL, + '2025-01-31', + 12345679801234, + 'Test Test data', + NULL, + 1234, + 1234567, + 2025, + NULL, + NULL, + 0, + '2025-02-01', + 0, + NULL, + NULL, + NULL, + NULL, + '2025-01-15', + NULL, + NULL, + NULL, + NULL, + NULL, + 1, + 0, + 0, + NULL, + 12346579801234, + 12345678901234, + NULL, + 'Long test data for varchar(1000)', + 12345678901234, + 'Very long test data for varchar(4000)... Very long test data for varchar(4000)... Very long test data for varchar(4000)... Very long test data for varchar(4000)... Very long test data for varchar(4000)...', + 0 + ); + + id = id + 1; + end + end + """ + ,""" + create or alter procedure run_test(a int) + returns (t_cnt int, t_diff bigint) + as + declare id bigint; + declare t_begin timestamp; + declare t_end timestamp; + begin + t_cnt = a; + t_begin = 'now'; + for + select id + from test_table + where + id >= 0 and id < :t_cnt + into :id do + update test_table set fld_50 = :t_cnt where id = :id; + t_end = 'now'; + t_diff = datediff(millisecond from :t_begin to :t_end); + suspend; + end + """ + ) + ) + + with act.db.connect() as con: + for x in ddl_lst: + con.execute_immediate(x) + con.commit() + + #-------------------------------------- + + cur = con.cursor() + rs = None + ps = cur.prepare('select t.* from run_test(?) t') + elapsed_time_ratios = [] + ms_prev = -1 + for n in (0.375, 0.75, 1.5, 3, 6, 12, 24, 48): + # d1 = py_dt.timedelta(0) + rs = cur.execute(ps, ( int(n * 1000),)) + t1 = py_dt.datetime.now() + cur.fetchall() + t2 = py_dt.datetime.now() + con.commit() + d1 = t2-t1 + ms_curr = d1.seconds*1000 + d1.microseconds//1000 + + if ms_prev > 0: + elapsed_time_ratios.append(ms_curr / ms_prev) + ms_prev = ms_curr + + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_msg = 'Expected: data dispersion is low.' + std_deviation = stdev(elapsed_time_ratios) + if std_deviation <= MAX_STD_DEV: + print(expected_msg) + else: + print(f'UNEXPECTED: standard deviation of elapsed time ratios is {std_deviation} - greater than {MAX_STD_DEV=}') + print(f'Elapsed time ratios: {elapsed_time_ratios}') + + act.expected_stdout = f""" + {expected_msg} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From f694c7da5b10c0fa8536973f59a97b4560e642b0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 12:09:25 +0300 Subject: [PATCH 0378/1064] Added/Updated tests\bugs\core_6248_test.py: Re-implmented code for building 'Attributes' line using mon$database values, see func check_db_hdr_info. Checked on Windows, 6.0.0.652, 5.0.3.1622 --- tests/bugs/core_6248_test.py | 136 +++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 63 deletions(-) diff --git a/tests/bugs/core_6248_test.py b/tests/bugs/core_6248_test.py index 809b8dcc..8e15301a 100644 --- a/tests/bugs/core_6248_test.py +++ b/tests/bugs/core_6248_test.py @@ -53,6 +53,13 @@ Because of this, subprocess.run() is used to invoke fbsvcmgr Checked on Windows and Linux, 4.0.1.2692 (SS/CS), 5.0.0.736 (SS/CS). + + [25.02.2025] pzotov + Order of attributes changed since 93db88 ("ODS14: header page refactoring (#8401)"): + mon_read_only is displayed now PRIOR to mon_shutdown_mode. + Re-implmented code for building 'Attributes' line using mon$database values, see func check_db_hdr_info. + Checked on Windows, 6.0.0.652, 5.0.3.1622 + JIRA: CORE-6248 FBTEST: bugs.core_6248 """ @@ -64,7 +71,8 @@ import platform from pathlib import Path #from difflib import unified_diff -#from firebird.driver import SrvRepairFlag + +from firebird.driver import connect import pytest from firebird.qa import * @@ -82,48 +90,40 @@ def check_db_hdr_info(act: Action, db_file_chk:Path, interested_patterns, capsys # 1. Obtain attributes from mon$database: get page buffers, 'build' attributes row and get sweep interval. # These values will be displayed in the form of three separate LINES, without column names. # Content of this output must be equal to gstat filtered values, with exception of leading spaces: - sql_txt = f""" - set list on; - - -- Make connect using local protocol. - -- NOTE: 'command error' raises here if length of '{db_file_chk}' (including qutes!) greater than 255. - connect '{db_file_chk}' user {act.db.user}; - - select - 'Page buffers ' || mon$page_buffers as " " - ,'Attributes ' || iif(trim(attr_list) = '', '', substring(attr_list from 2)) - as " " - ,'Sweep interval: ' || mon$sweep_interval as " " - from ( + + expected_attr_from_mon_db = '' + with connect(str(db_file_chk), user = act.db.user) as con: + cur = con.cursor() + sql = """ select - mon$page_buffers - ,mon$forced_writes - ,mon$backup_state - ,mon$reserve_space - ,mon$shutdown_mode - ,mon$read_only - ,mon$replica_mode - ,mon$sweep_interval - ,iif(mon$forced_writes = 1, ', force write', '') - || iif(mon$reserve_space = 0, ', no reserve', '') - || decode(mon$backup_state, 2, ', merge', 1, ', backup lock', '') - || decode(mon$shutdown_mode, 3, 'full shutdown', 2, ', single-user maintenance', 1, ', multi-user maintenance', '') - -- !! NEED TRIM() !! otherwise 10 spaces will be inserted if mon$read_only=0. - -- Discussed with Vladet al, letters since 23.09.2022 10:57. - || trim(iif(mon$read_only<>0, ', read only', '')) - || decode(mon$replica_mode, 2, ', read-write replica', 1, ', read-only replica', '') - as attr_list + rdb$get_context('SYSTEM', 'ENGINE_VERSION') as engine_ver + ,mon$page_buffers as mon_page_buffers + ,mon$sweep_interval as mon_sweep_interval + ,trim(iif(mon$forced_writes = 1, ', force write', '')) as mon_force_write + ,trim(iif(mon$reserve_space = 0, ', no reserve', '')) as mon_reserve_space + ,trim(decode(mon$backup_state, 2, ', merge', 1, ', backup lock', '')) as mon_backup_state + ,trim(decode(mon$shutdown_mode, 3, 'full shutdown', 2,', single-user maintenance', 1,', multi-user maintenance', '')) as mon_shutdown_mode + -- ::: NEED TRIM() ::: otherwise 10 spaces will be inserted if mon$read_only=0. + -- Discussed with Vlad et al, letters since 23.09.2022 10:57. + ,trim(iif(mon$read_only = 1, ', read only', '')) as mon_read_only + ,trim(decode(mon$replica_mode, 2,', read-write replica', 1,', read-only replica', '')) as mon_replica_mode from mon$database - ); - commit; - """ - # Example of output: - # Page buffers 3791 - # Attributes force write, no reserve, single-user maintenance, read only, read-write replica - # Sweep interval: 5678 - - act.isql(switches = ['-q'], input = sql_txt, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) - expected_attr_from_mon_db = act.stdout + """ + cur.execute(sql) + for r in cur: + engine_ver, mon_page_buffers, mon_sweep_interval, mon_force_write, mon_reserve_space, mon_backup_state, mon_shutdown_mode, mon_read_only, mon_replica_mode = r[:9] + + expected_attr_from_mon_db += f'Page buffers {mon_page_buffers}' + if act.is_version('<6'): + attr_list = f'{mon_force_write}{mon_reserve_space}{mon_backup_state}{mon_shutdown_mode}{mon_read_only}{mon_replica_mode}' + else: + ### ACHTUNG, SINCE 6.0.0.647 2025.02.21 ### + # Order of attributes has changed since #93db88 ("ODS14: header page refactoring (#8401)"), 20-feb-2025: + # mon_read_only is displayed now PRIOR to mon_shutdown_mode: + attr_list = f'{mon_force_write}{mon_reserve_space}{mon_backup_state}{mon_read_only}{mon_shutdown_mode}{mon_replica_mode}' + + expected_attr_from_mon_db += f'\nAttributes {attr_list[2:]}' + expected_attr_from_mon_db += f'\nSweep interval: {mon_sweep_interval}' #------------------------------------------------------ @@ -157,6 +157,7 @@ def check_db_hdr_info(act: Action, db_file_chk:Path, interested_patterns, capsys for line in act.stdout.split('\n'): print('gstat output: ',line) assert db_found,'COULD NOT FIND NAME OF DATABASE IN THE GSTAT HEADER' + # 3. Return GUID of database (can be compared after b/r with GUID of restored database: they always must differ): return db_guid @@ -176,17 +177,17 @@ def test_1(act: Action, tmp_file:Path, capsys): # All these (cuted) strings have length = 254 bytes and do NOT contain ending double quote. # Because of this, we must include this character into the pattern only as OPTIONAL, i.e.: |'Database\s+"\S+(")?'| # - interested_patterns = ( 'Database\s+"\S+(")?', '[\t ]*Attributes([\t ]+\w+)?', '[\t ]*Page buffers([\t ]+\d+)', '[\t ]*Sweep interval(:)?([\t ]+\d+)', 'Database GUID') + interested_patterns = ( r'Database\s+"\S+(")?', r'[\t ]*Attributes([\t ]+\w+)?', r'[\t ]*Page buffers([\t ]+\d+)', r'[\t ]*Sweep interval(:)?([\t ]+\d+)', 'Database GUID') interested_patterns = [re.compile(p, re.IGNORECASE) for p in interested_patterns] protocol_list = ('', 'inet://', 'xnet://') if os.name == 'nt' else ('', 'inet://',) full_str = str(tmp_file.absolute()) - for utility in ('gfix', 'fbsvcmgr'): + for chk_mode in ('fb_util', 'fbsvcmgr'): for protocol_prefix in protocol_list: # NB: most strict limit for DB filename length origins from isql 'CONNECT' command: - # 'command error' raises there if length of '{db_file_chk}' (including qutes!) greater than 255. + # 'command error' raises there if length of '{db_file_chk}' including qutes greater than 255. # Because of this, we can not operate with files with length of full name greater than 253 bytes. # db_file_len = 253 - len(protocol_prefix) @@ -195,9 +196,11 @@ def test_1(act: Action, tmp_file:Path, capsys): db_file_dif = Path(os.path.splitext(db_file_chk)[0] + '.dif') db_file_fbk = Path(os.path.splitext(db_file_chk)[0] + '.fbk') + db_file_dif.unlink(missing_ok = True) + db_file_dsn = '' svc_call_starting_part = [] - if utility == 'gfix': + if chk_mode == 'fb_util': db_file_dsn = protocol_prefix + str(db_file_chk) else: db_file_dsn = db_file_chk @@ -222,7 +225,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() svc_retcode = 0 - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-buffers', '3791', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_page_buffers', '3791', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -231,7 +234,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-write','sync', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_write_mode', 'prp_wm_sync', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -240,7 +243,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-housekeeping','5678', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_sweep_interval', '5678', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -249,7 +252,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-use','full', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_reserve_space', 'prp_res_use_full', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -258,7 +261,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-sweep', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_repair', 'rpr_sweep_db', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -267,7 +270,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() if act.is_version('>=4'): - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-replica','read_write', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_replica_mode', 'prp_rm_readwrite', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -278,31 +281,38 @@ def test_1(act: Action, tmp_file:Path, capsys): sql_txt = f""" -- Make connect using local protocol. - -- NOTE: 'command error' raises here if length of '{db_file_chk}' (including qutes!) greater than 255. + -- NOTE: 'command error' raises here if length of '{db_file_chk}' including qutes greater than 255. connect '{db_file_chk}' user {act.db.user}; alter database add difference file '{db_file_dif}'; alter database begin backup; - alter database set linger to 100; + -- alter database set linger to 100; """ + + # Page buffers 3791 + # Attributes force write, no reserve, backup lock, read-write replica + # Sweep interval: 5678 + # act.isql(switches = ['-q'], input = sql_txt, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout + + # WRONG for 4.x ... 5.x: assert '' == act.stdout -- noise characters are in output: + # "SQL> SQL> SQL> SQL> Database: ..." + act.reset() _ = check_db_hdr_info(act, db_file_chk, interested_patterns, capsys) - sql_txt = f""" -- Make connect using local protocol. - -- NOTE: 'command error' raises here if length of '{db_file_chk}' (including qutes!) greater than 255. + -- NOTE: 'command error' raises here if length of '{db_file_chk}' including qutes greater than 255. connect '{db_file_chk}' user {act.db.user}; - alter database set linger to 0; + -- alter database set linger to 0; alter database end backup; """ act.isql(switches = ['-q'], input = sql_txt, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout act.reset() - - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-mode','read_only', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_access_mode', 'prp_am_readonly', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -312,7 +322,7 @@ def test_1(act: Action, tmp_file:Path, capsys): _ = check_db_hdr_info(act, db_file_chk, interested_patterns, capsys) - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-shut','single', '-at', '20', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_shutdown_mode', 'prp_sm_single', 'prp_deny_new_attachments', '20', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -323,7 +333,7 @@ def test_1(act: Action, tmp_file:Path, capsys): src_guid = check_db_hdr_info(act, db_file_chk, interested_patterns, capsys) - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-online', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_properties', 'prp_online_mode', 'prp_sm_normal', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -332,7 +342,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gfix(switches=['-v', '-full', db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_repair', 'rpr_validate_db', 'rpr_full', 'dbname', db_file_chk], stderr = subprocess.STDOUT)).returncode @@ -341,7 +351,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gbak(switches=['-b', db_file_dsn, db_file_fbk], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_backup', 'dbname', db_file_chk, 'bkp_file', db_file_fbk], stderr = subprocess.STDOUT)).returncode @@ -350,7 +360,7 @@ def test_1(act: Action, tmp_file:Path, capsys): act.reset() - if utility == 'gfix': + if chk_mode == 'fb_util': act.gbak(switches=['-rep', db_file_fbk, db_file_dsn], combine_output = True, io_enc = locale.getpreferredencoding()) else: svc_retcode = (subprocess.run( svc_call_starting_part + ['action_restore', 'dbname', db_file_chk, 'bkp_file', db_file_fbk, 'res_replace' ], stderr = subprocess.STDOUT)).returncode From 24ee1cfc2b920cf711367753360d56af7d69470b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 12:13:47 +0300 Subject: [PATCH 0379/1064] Added/Updated tests\bugs\gh_8421_test.py: Reduced min_version to 5.0.3 after check on intermediate snapshot 5.0.3.1624-00b699c. --- tests/bugs/gh_8421_test.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_8421_test.py b/tests/bugs/gh_8421_test.py index 00a6be49..b9bf184c 100644 --- a/tests/bugs/gh_8421_test.py +++ b/tests/bugs/gh_8421_test.py @@ -30,13 +30,14 @@ good_ratios = [2.0357142857142856, 2.08187134502924, 1.9438202247191012, 2.066473988439306, 1.9713286713286713, 2.0503724725079815, 2.0278546712802767] stdev(good_ratios) = 0.05031744060704646 NOTES: - [24.01.2025] pzotov - Commit that fixed problem: + [25.01.2025] pzotov + Commits that fixed problem: 6.x: https://github.com/FirebirdSQL/firebird/commit/8d6c46e0e1f8eec374008e5ded6be119264ed3a6 + 5.x: https://github.com/FirebirdSQL/firebird/commit/00b699cc085278c26734bcfb4329d89a49d5d1e8 Test executes for ~30s. Confirmed problem on 6.0.0.647-9fccb55. - Checked on intermediate snapshot: 6.0.0.652-58633c8. + Checked on intermediate snapshots: 6.0.0.652-58633c8 (24.02.2025); 5.0.3.1624-00b699c (25.02.2025) """ from statistics import stdev @@ -53,7 +54,7 @@ MAX_STD_DEV = 0.5 ################# -@pytest.mark.version('>=6.0') +@pytest.mark.version('>=5.0.3') def test_1(act: Action, capsys): ddl_lst = [] ddl_lst.extend( From 72bdceb31cbbb4ed3213907291163c082e55b42e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 12:33:47 +0300 Subject: [PATCH 0380/1064] Added/Updated tests\bugs\gh_8291_test.py: Splitted code that defines value of MAX_ALLOWED_IDX_READS (see notes). Splitted code that defines value of MAX_ALLOWED_IDX_READS --- tests/bugs/gh_8291_test.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_8291_test.py b/tests/bugs/gh_8291_test.py index 701eeb37..cb01fab0 100644 --- a/tests/bugs/gh_8291_test.py +++ b/tests/bugs/gh_8291_test.py @@ -11,15 +11,15 @@ [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). + + [25.02.2025] pzotov + Splitted code that defines value of MAX_ALLOWED_IDX_READS: for 6.x it can be safely reduced to 6...10 since commit #5767b9. + Checked on intermediate snapshot 6.0.0.654-5767b9e. """ import pytest from firebird.qa import * -############################ -MAX_ALLOWED_IDX_READS = 1000 -############################ - init_sql = """ create table test (id int); @@ -48,6 +48,20 @@ @pytest.mark.version('>=5.0.2') def test_1(act: Action, capsys): + + # :::::::::::::::::::::::::::::: + # ::: T H R E S H O L D ::: + # :::::::::::::::::::::::::::::: + if act.is_version('<6'): + MAX_ALLOWED_IDX_READS = 1000 + else: + # NB. For the query that is used here number of indexed reads have been drastically reduced + # since #5767b9 (Ignore NULLs (if desired) while scanning keys during index navigation (#8446)). + # https://github.com/FirebirdSQL/firebird/commit/5767b9e522aa0b0ef36790f041a26bfd4f2fe738 + # https://github.com/FirebirdSQL/firebird/pull/8446 + # For 6.0.0.652 this value is 3 (three), so we can safely set it to 6...10 + MAX_ALLOWED_IDX_READS = 6 + msg_prefix = 'Number of indexed reads:' expected_txt = 'EXPECTED' idx_reads = {} From 7b7d0b35342740c5198e1f128903967b6e48ec1b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 17:15:47 +0300 Subject: [PATCH 0381/1064] Added/Updated tests\bugs\gh_8429_test.py: Method 'create_database()' uses LOCAL protocol if $QA_ROOT/firebir-driver.conf has no section [firebird.server.defaults]. If it is missed then encryption of db_file_c must be done at exclusive connection. Reduced indent to 'run_encr_decr()' call -- see notes. --- tests/bugs/gh_8429_test.py | 601 +++++++++++++++++++------------------ 1 file changed, 306 insertions(+), 295 deletions(-) diff --git a/tests/bugs/gh_8429_test.py b/tests/bugs/gh_8429_test.py index 415389ec..cd93077a 100644 --- a/tests/bugs/gh_8429_test.py +++ b/tests/bugs/gh_8429_test.py @@ -1,295 +1,306 @@ -#coding:utf-8 - -""" -ID: issue-8429 -ISSUE: https://github.com/FirebirdSQL/firebird/issues/8429 -TITLE: Segfault when already destroyed callback interface is used -DESCRIPTION: - Test uses THREE preliminary created aliases with KeyHolderPlugin that points to special configuration with name 'KH2'. - This configuration makes crypt plugin accept key ONLY from client app (in contrary to other encryption-related tests). - Three non-privileged users are created for this test. -NOTES: - [24.02.2025] pzotov - 1) firebird.conf must have KeyHolderPlugin = fbSampleKeyHolder and plugins/fbSampleKeyHolder.conf must have Auto = true. - 2) aliases gh_8429_alias_a, gh_8429_alias_b, gh_8429_alias_c that are used in this test must have (in databases.conf) - KeyHolderPlugin = KH2 and plugins.conf must contain: - --------------- - Plugin = KH2 { - Module = $(dir_plugins)/fbSampleKeyHolder - RegisterName = fbSampleKeyHolder - Config = KH2 - } - Config = KH2 { - Auto = false - } - --------------- - - 3) Third database (defined by 'gh_8429_alias_c') must be encrypted in FB-6.x in order to reproduce bug. - 4) All databases are created here by explicit 'create_database()' call and their deletion does NOT perform. - This was done intentionally in order to suppress appearance of any encryption-related errors that do not matter. - - Great thanks to Alex for provided scenario for this test (letter 10-feb-2025 20:43) ans lot of suggestions. - - Confirmed bug only for Super, snapshots: 6.0.0.600-188de60; 5.0.2.1606-a92f352; 4.0.6.3181-00b648f. - Classic not affected. - Checked on 6.0.0.607-1985b88; 5.0.2.1610-5e63ad0; 4.0.6.3185-9cac45a - all fine. -""" -import os -import time -import datetime as py_dt -import re -from pathlib import Path - -import pytest -from firebird.qa import * -from firebird.driver import create_database, ShutdownMode, ShutdownMethod - -########################### -### S E T T I N G S ### -########################### - -# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings -# from act.files_dir/'test_config.ini': -enc_settings = QA_GLOBALS['encryption'] - -# ACHTUNG: this must be carefully tuned on every new host: -# -MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN' if os.name == 'nt' else 'MAX_WAIT_FOR_ENCR_FINISH_NIX']) -assert MAX_WAITING_ENCR_FINISH > 0 - -ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt - -db = db_factory() -usr_x = user_factory('db', name = 'tmp_8429_x', password = 'tmp_8429_x', plugin = 'Srp') -usr_y = user_factory('db', name = 'tmp_8429_y', password = 'tmp_8429_y', plugin = 'Srp') -usr_z = user_factory('db', name = 'tmp_8429_z', password = 'tmp_8429_z', plugin = 'Srp') - -db_a = db_factory(filename = '#gh_8429_alias_a', do_not_create = True, do_not_drop = True) -db_b = db_factory(filename = '#gh_8429_alias_b', do_not_create = True, do_not_drop = True) -db_c = db_factory(filename = '#gh_8429_alias_c', do_not_create = True, do_not_drop = True) - -act_a = python_act('db_a') -act_b = python_act('db_b') -act_c = python_act('db_c') - -#---------------------------------------------------- - -def get_filename_by_alias(act: Action, alias_from_dbconf = None): - - if not alias_from_dbconf: - alias_from_dbconf = act.db.db_path - - # Scan line-by-line through databases.conf, find line starting with and extract name of file that - # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). - # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': - p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + alias_from_dbconf + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) - fname_in_dbconf = None - - with open(act.home_dir/'databases.conf', 'r') as f: - for line in f: - if p_required_alias_ptn.search(line): - # If databases.conf contains line like this: - # tmp_6147_alias = $(dir_sampleDb)/qa/tmp_core_6147.fdb - # - then we extract filename: 'tmp_core_6147.fdb' (see below): - fname_in_dbconf = Path(line.split('=')[1].strip()).name - break - - # if 'fname_in_dbconf' remains undefined here then propably not equals to specified in the databases.conf! - # - assert fname_in_dbconf - - #------------------------------------------------------------------ - # Full path + filename of database to which we will try to connect: - # - tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) - - return tmp_fdb - -#----------------------------------------------------------------------- - -def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): - if mode == 'encrypt': - # See letter from Alex, 15.12.2023 16:16 demo-plugin can not transfer named key over network. - # Because of that, we have to use 'ALTER DATABASE ENCRYPT WITH ' _WITHOUT_ adding 'key "{ENCRYPTION_KEY}"'. - # ::: NB ::: One need to be sure that $FB_HOME/plugins.conf contains following lines: - # Plugin = KH2 { - # Module = $(dir_plugins)/fbSampleKeyHolder - # RegisterName = fbSampleKeyHolder - # Config = KH2 - # } - # Config = KH2 { - # Auto = false - # } - # Otherwise error will raise: - # unsuccessful metadata update - # -ALTER DATABASE failed - # -Missing database encryption key for your attachment - # -Plugin fbSampleDbCrypt: - # -Crypt key not set - # - alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}"' # <<< ::: NB ::: DO NOT add '... key "{ENCRYPTION_KEY}"' here! - wait_for_state = 'Database encrypted' - elif mode == 'decrypt': - alter_db_sttm = 'alter database decrypt' - wait_for_state = 'Database not encrypted' - - - e_thread_finished = False - - # 0 = non crypted; - # 1 = has been encrypted; - # 2 = is DEcrypting; - # 3 = is Encrypting; - # - REQUIRED_CRYPT_STATE = 1 if mode == 'encrypt' else 0 - current_crypt_state = -1 - d1 = py_dt.timedelta(0) - with act.db.connect() as con: - cur = con.cursor() - ps, rs = None, None - try: - ps = cur.prepare('select mon$crypt_state from mon$database') - t1=py_dt.datetime.now() - d1 = t1-t1 - con.execute_immediate(alter_db_sttm) - con.commit() - while True: - t2=py_dt.datetime.now() - d1=t2-t1 - if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: - break - - # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. - # We have to store result of cur.execute() in order to - # close it explicitly. - # Otherwise AV can occur during Python garbage collection and this - # causes pytest to hang on its final point. - # Explained by hvlad, email 26.10.24 17:42 - rs = cur.execute(ps) - for r in rs: - ###################################################### - ### C H E C K M O N $ C R Y P T _ S T A T E ### - ###################################################### - current_crypt_state = r[0] - con.commit() - if current_crypt_state == REQUIRED_CRYPT_STATE: - e_thread_finished = True - break - else: - time.sleep(0.5) - except DatabaseError as e: - print( e.__str__() ) - print(e.gds_codes) - finally: - if rs: - rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS - if ps: - ps.free() - - - assert e_thread_finished, f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms; current_crypt_state={current_crypt_state}' - - -#----------------------------------------------------------------------- - -@pytest.mark.es_eds -@pytest.mark.encryption -@pytest.mark.version('>=4.0.6') -def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User, usr_z: User, capsys): - - dbfile_a = get_filename_by_alias(act_a) - dbfile_b = get_filename_by_alias(act_b) - dbfile_c = get_filename_by_alias(act_c) - - dbfile_a.unlink(missing_ok = True) - dbfile_b.unlink(missing_ok = True) - dbfile_c.unlink(missing_ok = True) - - with create_database(act_a.db.db_path, user = act_a.db.user, password = act_a.db.password) as con_a, \ - create_database(act_b.db.db_path, user = act_b.db.user, password = act_b.db.password) as con_b, \ - create_database(act_c.db.db_path, user = act_c.db.user, password = act_c.db.password) as con_c: - - sql = f""" - create procedure sp_a (a_who varchar(31)) returns (o_info varchar(512)) as - begin - -- e1-meta.sql: - execute statement 'select * from sp_b(''' || a_who || ''')' as user '{usr_x.name}' password '{usr_x.password}' on external 'gh_8429_alias_b' into o_info; - suspend; - end - ^ - grant execute on procedure sp_a to public - ^ - alter database set linger to 0 - ^ - """ - for x in sql.split('^'): - if (s := x.strip()): - con_a.execute_immediate(s) - con_a.commit() - - # .................................................. - - sql = f""" - create procedure sp_b (a_who varchar(31)) returns (o_info varchar(512)) as - begin - execute statement 'select * from sp_c' as user a_who password a_who on external 'gh_8429_alias_c' into o_info; - suspend; - end - ^ - grant execute on procedure sp_b to public - ^ - alter database set linger to 0 - ^ - """ - for x in sql.split('^'): - if (s := x.strip()): - con_b.execute_immediate(s) - con_b.commit() - - # .................................................. - - sql = f""" - create procedure sp_c returns (o_info varchar(512)) as - begin - o_info = lower(current_user); - -- o_info = lower(rdb$get_context('SYSTEM', 'DB_NAME')) || ':' || lower(current_user); - suspend; - end - ^ - grant execute on procedure sp_c to public - ^ - alter database set linger to 0 - ^ - """ - for x in sql.split('^'): - if (s := x.strip()): - con_c.execute_immediate(s) - con_c.commit() - - ############################################ - ### E N C R Y P T D A T A B A S E ### - ############################################ - run_encr_decr(act_c, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys) - - # .................................................. - - - with act_a.db.connect() as con_a: - cur = con_a.cursor() - cur.execute(f"select o_info from sp_a('{usr_x.name.lower()}')") - for r in cur: - print(r[0]) - - with act_a.db.connect() as con_a: - cur = con_a.cursor() - cur.execute(f"select o_info from sp_a('{usr_y.name.lower()}')") - for r in cur: - print(r[0]) - - act_a.expected_stdout = f""" - {usr_x.name.lower()} - {usr_y.name.lower()} - """ - act_a.stdout = capsys.readouterr().out - assert act_a.clean_stdout == act_a.clean_expected_stdout - act_a.reset() +#coding:utf-8 + +""" +ID: issue-8429 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8429 +TITLE: Segfault when already destroyed callback interface is used +DESCRIPTION: + Test uses THREE preliminary created aliases with KeyHolderPlugin that points to special configuration with name 'KH2'. + This configuration makes crypt plugin accept key ONLY from client app (in contrary to other encryption-related tests). + Three non-privileged users are created for this test. +NOTES: + [24.02.2025] pzotov + 1) firebird.conf must have KeyHolderPlugin = fbSampleKeyHolder and plugins/fbSampleKeyHolder.conf must have Auto = true. + 2) aliases gh_8429_alias_a, gh_8429_alias_b, gh_8429_alias_c that are used in this test must have (in databases.conf) + KeyHolderPlugin = KH2 and plugins.conf must contain: + --------------- + Plugin = KH2 { + Module = $(dir_plugins)/fbSampleKeyHolder + RegisterName = fbSampleKeyHolder + Config = KH2 + } + Config = KH2 { + Auto = false + } + --------------- + + 3) Third database (defined by 'gh_8429_alias_c') must be encrypted in FB-6.x in order to reproduce bug. + 4) All databases are created here by explicit 'create_database()' call and their deletion does NOT perform. + This was done intentionally in order to suppress appearance of any encryption-related errors that do not matter. + 5) Method 'create_database()' uses LOCAL protocol if $QA_ROOT/firebir-driver.conf has no section [firebird.server.defaults] + It can be empty but it MUST present if we want database to be created using prefix 'inet://' for its DSN. + Because of that, encryption of db_file_c will be done at exclusive connection, see reduced indent for 'run_encr_decr()' call. + + Great thanks to Alex for provided scenario for this test (letter 10-feb-2025 20:43) ans lot of suggestions. + + Confirmed bug only for Super, snapshots: 6.0.0.600-188de60; 5.0.2.1606-a92f352; 4.0.6.3181-00b648f. + Classic not affected. + Checked on 6.0.0.607-1985b88; 5.0.2.1610-5e63ad0; 4.0.6.3185-9cac45a - all fine. +""" +import os +import time +import datetime as py_dt +import re +from pathlib import Path + +import pytest +from firebird.qa import * +from firebird.driver import create_database, ShutdownMode, ShutdownMethod + +########################### +### S E T T I N G S ### +########################### + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +enc_settings = QA_GLOBALS['encryption'] + +# ACHTUNG: this must be carefully tuned on every new host: +# +MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN' if os.name == 'nt' else 'MAX_WAIT_FOR_ENCR_FINISH_NIX']) +assert MAX_WAITING_ENCR_FINISH > 0 + +ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt + +db = db_factory() +usr_x = user_factory('db', name = 'tmp_8429_x', password = 'tmp_8429_x', plugin = 'Srp') +usr_y = user_factory('db', name = 'tmp_8429_y', password = 'tmp_8429_y', plugin = 'Srp') +usr_z = user_factory('db', name = 'tmp_8429_z', password = 'tmp_8429_z', plugin = 'Srp') + +db_a = db_factory(filename = '#gh_8429_alias_a', do_not_create = True, do_not_drop = True) +db_b = db_factory(filename = '#gh_8429_alias_b', do_not_create = True, do_not_drop = True) +db_c = db_factory(filename = '#gh_8429_alias_c', do_not_create = True, do_not_drop = True) + +act_a = python_act('db_a') +act_b = python_act('db_b') +act_c = python_act('db_c') + +#---------------------------------------------------- + +def get_filename_by_alias(act: Action, alias_from_dbconf = None): + + if not alias_from_dbconf: + alias_from_dbconf = act.db.db_path + + # Scan line-by-line through databases.conf, find line starting with and extract name of file that + # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). + # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': + p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + alias_from_dbconf + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE ) + fname_in_dbconf = None + + with open(act.home_dir/'databases.conf', 'r') as f: + for line in f: + if p_required_alias_ptn.search(line): + # If databases.conf contains line like this: + # tmp_6147_alias = $(dir_sampleDb)/qa/tmp_core_6147.fdb + # - then we extract filename: 'tmp_core_6147.fdb' (see below): + fname_in_dbconf = Path(line.split('=')[1].strip()).name + break + + # if 'fname_in_dbconf' remains undefined here then propably not equals to specified in the databases.conf! + # + assert fname_in_dbconf + + #------------------------------------------------------------------ + # Full path + filename of database to which we will try to connect: + # + tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) + + return tmp_fdb + +#----------------------------------------------------------------------- + +def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys): + if mode == 'encrypt': + # See letter from Alex, 15.12.2023 16:16 demo-plugin can not transfer named key over network. + # Because of that, we have to use 'ALTER DATABASE ENCRYPT WITH ' _WITHOUT_ adding 'key "{ENCRYPTION_KEY}"'. + # ::: NB ::: One need to be sure that $FB_HOME/plugins.conf contains following lines: + # Plugin = KH2 { + # Module = $(dir_plugins)/fbSampleKeyHolder + # RegisterName = fbSampleKeyHolder + # Config = KH2 + # } + # Config = KH2 { + # Auto = false + # } + # Otherwise error will raise: + # unsuccessful metadata update + # -ALTER DATABASE failed + # -Missing database encryption key for your attachment + # -Plugin fbSampleDbCrypt: + # -Crypt key not set + # + alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}"' # <<< ::: NB ::: DO NOT add '... key "{ENCRYPTION_KEY}"' here! + wait_for_state = 'Database encrypted' + elif mode == 'decrypt': + alter_db_sttm = 'alter database decrypt' + wait_for_state = 'Database not encrypted' + + + e_thread_finished = False + + # 0 = non crypted; + # 1 = has been encrypted; + # 2 = is DEcrypting; + # 3 = is Encrypting; + # + REQUIRED_CRYPT_STATE = 1 if mode == 'encrypt' else 0 + current_crypt_state = -1 + d1 = py_dt.timedelta(0) + with act.db.connect() as con: + cur = con.cursor() + ps, rs = None, None + try: + ps = cur.prepare('select mon$crypt_state from mon$database') + t1=py_dt.datetime.now() + d1 = t1-t1 + con.execute_immediate(alter_db_sttm) + con.commit() + while True: + t2=py_dt.datetime.now() + d1=t2-t1 + if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish: + break + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps) + for r in rs: + ###################################################### + ### C H E C K M O N $ C R Y P T _ S T A T E ### + ###################################################### + current_crypt_state = r[0] + con.commit() + if current_crypt_state == REQUIRED_CRYPT_STATE: + e_thread_finished = True + break + else: + time.sleep(0.5) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + + assert e_thread_finished, f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms; current_crypt_state={current_crypt_state}' + + +#----------------------------------------------------------------------- + +@pytest.mark.es_eds +@pytest.mark.encryption +@pytest.mark.version('>=4.0.6') +def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User, usr_z: User, capsys): + + # ::: NB ::: + # Encryption required for db_file_c in order to reproduce problem on FB 6.x + # Because of that, this DB can be inaccessibe something was wrong in previous run of this test. + # Thus we have to create all databases now (rather than use previously created): + # + dbfile_a = get_filename_by_alias(act_a) + dbfile_b = get_filename_by_alias(act_b) + dbfile_c = get_filename_by_alias(act_c) + + dbfile_a.unlink(missing_ok = True) + dbfile_b.unlink(missing_ok = True) + dbfile_c.unlink(missing_ok = True) + + # ::: NB ::: + # 'create_database()' will use LOCAL protocol if $QA_ROOT/firebir-driver.conf has no section [firebird.server.defaults] + # It can be empty but it MUST present if we want database to be created using prefix 'inet://' for its DSN. + # + with create_database(act_a.db.db_path, user = act_a.db.user, password = act_a.db.password) as con_a, \ + create_database(act_b.db.db_path, user = act_b.db.user, password = act_b.db.password) as con_b, \ + create_database(act_c.db.db_path, user = act_c.db.user, password = act_c.db.password) as con_c: + + sql = f""" + create procedure sp_a (a_who varchar(31)) returns (o_info varchar(512)) as + begin + -- e1-meta.sql: + execute statement 'select * from sp_b(''' || a_who || ''')' as user '{usr_x.name}' password '{usr_x.password}' on external 'gh_8429_alias_b' into o_info; + suspend; + end + ^ + grant execute on procedure sp_a to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_a.execute_immediate(s) + con_a.commit() + + # .................................................. + + sql = f""" + create procedure sp_b (a_who varchar(31)) returns (o_info varchar(512)) as + begin + execute statement 'select * from sp_c' as user a_who password a_who on external 'gh_8429_alias_c' into o_info; + suspend; + end + ^ + grant execute on procedure sp_b to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_b.execute_immediate(s) + con_b.commit() + + # .................................................. + + sql = f""" + create procedure sp_c returns (o_info varchar(512)) as + begin + o_info = lower(current_user); + -- o_info = lower(rdb$get_context('SYSTEM', 'DB_NAME')) || ':' || lower(current_user); + suspend; + end + ^ + grant execute on procedure sp_c to public + ^ + alter database set linger to 0 + ^ + """ + for x in sql.split('^'): + if (s := x.strip()): + con_c.execute_immediate(s) + con_c.commit() + # < close all connections + + ############################################ + ### E N C R Y P T D A T A B A S E ### + ############################################ + # Run encryption. No concurrent connection must be here to db_file_c: + run_encr_decr(act_c, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys) + + with act_a.db.connect() as con_a: + cur = con_a.cursor() + cur.execute(f"select o_info from sp_a('{usr_x.name.lower()}')") + for r in cur: + print(r[0]) + + with act_a.db.connect() as con_a: + cur = con_a.cursor() + cur.execute(f"select o_info from sp_a('{usr_y.name.lower()}')") + for r in cur: + print(r[0]) + + act_a.expected_stdout = f""" + {usr_x.name.lower()} + {usr_y.name.lower()} + """ + act_a.stdout = capsys.readouterr().out + assert act_a.clean_stdout == act_a.clean_expected_stdout + act_a.reset() From 87d6d86d8460e316c67607a663c2b6177660168b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 17:29:34 +0300 Subject: [PATCH 0382/1064] Added/Updated tests\bugs\gh_8429_test.py: added cleanup code. Removed unneeded set of linger. --- tests/bugs/gh_8429_test.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/bugs/gh_8429_test.py b/tests/bugs/gh_8429_test.py index cd93077a..8f04394d 100644 --- a/tests/bugs/gh_8429_test.py +++ b/tests/bugs/gh_8429_test.py @@ -231,8 +231,6 @@ def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User ^ grant execute on procedure sp_a to public ^ - alter database set linger to 0 - ^ """ for x in sql.split('^'): if (s := x.strip()): @@ -250,8 +248,6 @@ def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User ^ grant execute on procedure sp_b to public ^ - alter database set linger to 0 - ^ """ for x in sql.split('^'): if (s := x.strip()): @@ -270,8 +266,6 @@ def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User ^ grant execute on procedure sp_c to public ^ - alter database set linger to 0 - ^ """ for x in sql.split('^'): if (s := x.strip()): @@ -291,11 +285,23 @@ def test_1(act_a: Action, act_b: Action, act_c: Action, usr_x: User, usr_y: User for r in cur: print(r[0]) + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # this caused crash before fix: + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ with act_a.db.connect() as con_a: cur = con_a.cursor() cur.execute(f"select o_info from sp_a('{usr_y.name.lower()}')") for r in cur: print(r[0]) + + ######### + # CLEANUP + ######### + for a in (act_a, act_b, act_c): + with a.db.connect() as con: + con.execute_immediate('ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL') + con.commit() + con.drop_database() act_a.expected_stdout = f""" {usr_x.name.lower()} From 7009906c63a136e04b72c6a191cf53099dec1cdf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 22:31:00 +0300 Subject: [PATCH 0383/1064] Added/Updated tests\bugs\core_6043_test.py: avoid mention 'PermissionError' in comments because it can be wrongly interpreted during pasring QA results --- tests/bugs/core_6043_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_6043_test.py b/tests/bugs/core_6043_test.py index f592875a..bece765d 100644 --- a/tests/bugs/core_6043_test.py +++ b/tests/bugs/core_6043_test.py @@ -76,7 +76,7 @@ def test_1(act: Action, capsys): # tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) - # PermissionError: [Errno 13] Permission denied --> probably because + # Permiss. Error: [Errno 13] Permiss. denied --> probably because # Firebird was started by root rather than current (non-privileged) user. # tmp_fdb.write_bytes(act.db.db_path.read_bytes()) From 38a2720687a8600f5bbb46c9878872d0c450cac5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 25 Feb 2025 22:31:15 +0300 Subject: [PATCH 0384/1064] Added/Updated tests\bugs\core_4964_test.py: avoid mention 'PermissionError' in comments because it can be wrongly interpreted during pasring QA results --- tests/bugs/core_4964_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_4964_test.py b/tests/bugs/core_4964_test.py index 81836d2f..15536ad5 100644 --- a/tests/bugs/core_4964_test.py +++ b/tests/bugs/core_4964_test.py @@ -97,7 +97,7 @@ def test_1(act: Action, tmp_user: User, capsys): # tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) - # PermissionError: [Errno 13] Permission denied --> probably because + # Permiss. Error: [Errno 13] Permiss. denied --> probably because # Firebird was started by root rather than current (non-privileged) user. # tmp_fdb.write_bytes(act.db.db_path.read_bytes()) From 616b304164c0ee581f1c27e64037f2ffb093bc34 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 26 Feb 2025 00:15:18 +0300 Subject: [PATCH 0385/1064] Added/changed aliased for core_4964_test.py --- files/qa-databases.conf | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/files/qa-databases.conf b/files/qa-databases.conf index 5209df51..23d9c767 100644 --- a/files/qa-databases.conf +++ b/files/qa-databases.conf @@ -14,13 +14,24 @@ # Test issue: https://github.com/FirebirdSQL/firebird/issues/5160 # https://github.com/FirebirdSQL/firebird/issues/5255 # ex. core-4964 -tmp_core_4964_alias = $(dir_sampleDb)/qa/tmp_core_4964.fdb +tmp_core_4964_alias_5x = $(dir_sampleDb)/qa/tmp_core_4964_5x.fdb { # dir_msg - directory where messages file (firebird.msg) is located. # We put here path+name of file that has for sure not .fdb format: SecurityDatabase = $(dir_msg)/firebird.msg } +tmp_core_4964_alias_win = $(dir_sampleDb)/qa/tmp_core_4964_win.fdb +{ + SecurityDatabase = $(dir_sample)/prebuilt/plugins/fbSampleDbCrypt.dll + # SecurityDatabase = $(dir_sample)/prebuilt/bin/fbSampleDbCryptApp.exe +} + +tmp_core_4964_alias_nix = $(dir_sampleDb)/qa/tmp_core_4964_nix.fdb +{ + SecurityDatabase = $(dir_sample)/prebuilt/plugins/libfbSampleDbCrypt.so + # SecurityDatabase = $(dir_sample)/prebuilt/bin/fbSampleDbCryptApp +} # Test issue: https://github.com/FirebirdSQL/firebird/issues/5160 # ex. core-4864 From 241f73b24a856ab1f121d01ff68d9fe35bef1b54 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 26 Feb 2025 00:16:18 +0300 Subject: [PATCH 0386/1064] =?UTF-8?q?Added/Updated=20tests\bugs\core=5F496?= =?UTF-8?q?4=5Ftest.py:=20added=20two=20aliases=20with=20SecurityDatabase?= =?UTF-8?q?=20that=20points=20to=20library=20fbSampleDbCrypt=20-=20=D1=8B?= =?UTF-8?q?=D1=83=D1=83=20=D1=82=D1=89=D0=B5=D1=83=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/bugs/core_4964_test.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4964_test.py b/tests/bugs/core_4964_test.py index 15536ad5..efb77963 100644 --- a/tests/bugs/core_4964_test.py +++ b/tests/bugs/core_4964_test.py @@ -38,8 +38,24 @@ Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/27 Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux. -""" + [26.02.2025] pzotov + Old alias renamed to 'tmp_core_4964_alias_5x' - it will be used only for FB 3.x ... 5.x. + For 6.x+: added two aliases (for Windows and Linux) in the preliminary created databases.conf: 'tmp_core_4964_alias_win' and 'tmp_core_4964_alias_nix'. + Both contain SecurityDatabase that points to library fbSampleDbCrypt.dll (Linux: libfbSampleDbCrypt.so) which is binary file and its signature DIFFERS + from firebird.msg which was in use before. + The problem appeared since 6.0.0.647 (21.02.2025) when ODS was changed. Among other changes, FB does not do additional check for header, i.e.: + *** WAS: *** + if (header->hdr_header.pag_type != pag_header || header->hdr_sequence) + ERR_post; + *** NOW: *** + if (header->hdr_header.pag_type != pag_header) + ERR_post; + (field 'header->hdr_sequence' no more exists). + But firebird.msg starting byte is 0x01 - and this is equal to pag_header, thus firebird.msg is no more suitable for this test in 6.x. + Explained by dimitr, letter 25.02.2025 22:45 +""" +import os import re import time from pathlib import Path @@ -53,8 +69,6 @@ ,('(-)?file .* is not a valid database', 'file is not a valid database') ] -REQUIRED_ALIAS = 'tmp_core_4964_alias' - db = db_factory() act = python_act('db', substitutions = substitutions) tmp_user = user_factory('db', name='tmp$c4964', password='123', plugin = 'Srp') @@ -72,6 +86,11 @@ @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User, capsys): + if act.is_version('<6'): + REQUIRED_ALIAS = 'tmp_core_4964_alias_5x' + else: + REQUIRED_ALIAS = 'tmp_core_4964_alias_win' if os.name == 'nt' else 'tmp_core_4964_alias_nix' + fblog_1 = act.get_firebird_log() # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that From c89d52946cdbfe114fed6d3234a2436d62e9e9be Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 26 Feb 2025 09:18:31 +0300 Subject: [PATCH 0387/1064] Added/Updated tests\bugs\gh_8421_test.py: Separated values of MAX_STD_DEV depending on OS. It seems that for Linux one need to allow greater std dev. --- tests/bugs/gh_8421_test.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_8421_test.py b/tests/bugs/gh_8421_test.py index b9bf184c..6ac151f7 100644 --- a/tests/bugs/gh_8421_test.py +++ b/tests/bugs/gh_8421_test.py @@ -39,7 +39,7 @@ Confirmed problem on 6.0.0.647-9fccb55. Checked on intermediate snapshots: 6.0.0.652-58633c8 (24.02.2025); 5.0.3.1624-00b699c (25.02.2025) """ - +import os from statistics import stdev import time import datetime as py_dt @@ -50,12 +50,14 @@ db = db_factory() act = python_act('db') -################# -MAX_STD_DEV = 0.5 -################# - @pytest.mark.version('>=5.0.3') def test_1(act: Action, capsys): + + ############################################# + MAX_STD_DEV = 0.5 if os.name == 'nt' else 0.8 + ############################################# + + ddl_lst = [] ddl_lst.extend( ( From 93449826b2bbbbd36fd03e99f22ae62afd0687bd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 26 Feb 2025 11:24:50 +0300 Subject: [PATCH 0388/1064] Added/Updated tests\bugs\gh_6976_test.py: Increased valueTHRESHOLD_FOR_MAKE_CONNECT_MS for servermode = 'Super': on poor hardware previous value was not enough --- tests/bugs/gh_6976_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_6976_test.py b/tests/bugs/gh_6976_test.py index 7f762e9c..c28543e6 100644 --- a/tests/bugs/gh_6976_test.py +++ b/tests/bugs/gh_6976_test.py @@ -21,7 +21,6 @@ NOTES: [20.07.2022] pzotov - Bug reproduced on 4.0.1.2606 but only when it is tested just after 5.0.0.591. In that case firebird.log will have following messages: @@ -48,7 +47,6 @@ [localized message can be here]: "operation completed successfully" NB: time interval between 01:25:17 and 01:27:07 is exactly 110 seconds. - On recent FB 4.x and 5.x median duration for delivering error to client must be about 80 ms. On 4.0.1.2606 this was about 640 ms (in case when it was tested without previous 5.x test). @@ -56,12 +54,14 @@ Recent FB build show that time to wait exception with expected gdscode = 335544344 must be less than 300 ms but it depends on ServerMode (for Classic it is about 2x more than for Super). Median value will be compared with THRESHOLD_FOR_MAKE_CONNECT_MS variable.. - Each attempt to connect top broken DB must bring stack with TWO gdscodes: isc_io_error = 335544344; isc_io_read_err = 335544736; - Checked on Windows: 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 + + [26.02.2025] pzotov + Increased valueTHRESHOLD_FOR_MAKE_CONNECT_MS for servermode = 'Super': on poor hardware + previous value was not enough. Problem appeared on 6.0.0.655, Windows 10, build 19045.3086. """ import os @@ -150,7 +150,7 @@ def try_cuted_off_db(act_source, act_broken, db_page_size, db_pages_cnt, cut_off @pytest.mark.platform('Windows') def test_1(act_source: Action, act_broken: Action, capsys): - THRESHOLD_FOR_MAKE_CONNECT_MS = 250 if 'classic' in act_source.vars['server-arch'].lower() else 100 + THRESHOLD_FOR_MAKE_CONNECT_MS = 250 if 'classic' in act_source.vars['server-arch'].lower() else 150 with act_source.db.connect() as con: db_page_size = con.info.page_size From 314c17a7d949b265ef719a4fa4aacebb34b2ed9c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 26 Feb 2025 12:22:18 +0300 Subject: [PATCH 0389/1064] Added/Updated tests\functional\dml\skip_locked\test_skip_locked_basic.py: added basic test for check SKIP LOCKED func. --- .../dml/skip_locked/test_skip_locked_basic.py | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 tests/functional/dml/skip_locked/test_skip_locked_basic.py diff --git a/tests/functional/dml/skip_locked/test_skip_locked_basic.py b/tests/functional/dml/skip_locked/test_skip_locked_basic.py new file mode 100644 index 00000000..0549090f --- /dev/null +++ b/tests/functional/dml/skip_locked/test_skip_locked_basic.py @@ -0,0 +1,106 @@ +#coding:utf-8 + +""" +ID: dml.skip_locked +TITLE: Basic check of SKIP LOCKED +DESCRIPTION: + Trivial test to check SKIP LOCKED functionality on all kinds of transaction isolation level. + More complex cases see in gh_7350_test.py. +NOTES: + [26.02.2025] pzotov + Commit that introduced this feature (5.0.0.811, 29-oct-2022): + https://github.com/FirebirdSQL/firebird/commit/5cc8a8f7fd27d72d5ca6f19eb691e93f2404ddd1 +""" +from firebird.driver import tpb, Isolation, DatabaseError + +import pytest +from firebird.qa import * + +init_script = \ +f''' + set bail on; + recreate table test(id int primary key, f01 int); + commit; + insert into test(id, f01) select row_number()over(), 0 from rdb$types rows 10; + commit; +''' + +db = db_factory(init = init_script ) +act = python_act('db') + +@pytest.mark.version('>=5.0') +def test_1(act: Action, capsys): + + tx_isol_lst = [ + Isolation.SERIALIZABLE, + Isolation.SNAPSHOT, + Isolation.READ_COMMITTED_NO_RECORD_VERSION, + Isolation.READ_COMMITTED_RECORD_VERSION, + ] + if act.is_version('>=4'): + tx_isol_lst.append(Isolation.READ_COMMITTED_READ_CONSISTENCY) + + with act.db.connect() as con_locker, act.db.connect() as con_worker: + con_locker.execute_immediate('update test set f01 = 1 where id in (1,5,9)') + for x_isol in tx_isol_lst: + custom_tpb = tpb(isolation = x_isol, lock_timeout = 0) + print(x_isol.name) + tx_worker = con_worker.transaction_manager(custom_tpb) + tx_worker.begin() + cur = tx_worker.cursor() + cur.execute('select id from test with lock skip locked') + try: + for r in cur: + print('TIL:',x_isol.name, 'ID:', r[0]) + except DatabaseError as e: + print(e) + # E firebird.driver.types.DatabaseError: lock conflict on no wait transaction + # E -Acquire lock for relation (TEST) failed + + cur.close() + tx_worker.rollback() + + act.expected_stdout = """ + SERIALIZABLE + lock conflict on no wait transaction + -Acquire lock for relation (TEST) failed + + SNAPSHOT + TIL: SNAPSHOT ID: 2 + TIL: SNAPSHOT ID: 3 + TIL: SNAPSHOT ID: 4 + TIL: SNAPSHOT ID: 6 + TIL: SNAPSHOT ID: 7 + TIL: SNAPSHOT ID: 8 + TIL: SNAPSHOT ID: 10 + + READ_COMMITTED_NO_RECORD_VERSION + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 2 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 3 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 4 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 6 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 7 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 8 + TIL: READ_COMMITTED_NO_RECORD_VERSION ID: 10 + + READ_COMMITTED_RECORD_VERSION + TIL: READ_COMMITTED_RECORD_VERSION ID: 2 + TIL: READ_COMMITTED_RECORD_VERSION ID: 3 + TIL: READ_COMMITTED_RECORD_VERSION ID: 4 + TIL: READ_COMMITTED_RECORD_VERSION ID: 6 + TIL: READ_COMMITTED_RECORD_VERSION ID: 7 + TIL: READ_COMMITTED_RECORD_VERSION ID: 8 + TIL: READ_COMMITTED_RECORD_VERSION ID: 10 + + READ_COMMITTED_READ_CONSISTENCY + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 2 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 3 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 4 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 6 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 7 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 8 + TIL: READ_COMMITTED_READ_CONSISTENCY ID: 10 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From abbcbfb87391319c00dca6c7f8b3367efb4bdc54 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 28 Feb 2025 01:13:37 +0300 Subject: [PATCH 0390/1064] Added/Updated tests\bugs\gh_8444_test.py: Checked on 6.0.0.656-25fb454 --- tests/bugs/gh_8444_test.py | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/bugs/gh_8444_test.py diff --git a/tests/bugs/gh_8444_test.py b/tests/bugs/gh_8444_test.py new file mode 100644 index 00000000..fdea236c --- /dev/null +++ b/tests/bugs/gh_8444_test.py @@ -0,0 +1,65 @@ +#coding:utf-8 + +""" +ID: issue-8444 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8444 +TITLE: GBAK: GDS error batch_big_seg2 when restoring a table with many BLOBs +DESCRIPTION: +NOTES: + [28.02.2025] pzotov + 1) restore must use remote protocol, i.e. 'localhost:' must be specified in DSN of target FDB. + 2) in case of success test executes for ~60 seconds. + Confirmed problem on 6.0.0.655-6e3e059, 5.0.3.1624-00b699c: restore terminates prematurely, gbak crashes (with retcode=3221225477). + Checked on 6.0.0.656-25fb454 +""" +from pathlib import Path +import zipfile +import locale +import re +import pytest +from firebird.qa import * + +db = db_factory() +act = python_act('db') +tmp_fbk = temp_file('gh_8444.tmp.fbk') +tmp_fdb = temp_file('gh_8444.tmp.fdb') + +expected_stdout = """ + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags +""" + +@pytest.mark.version('>=5.0.3') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_8444.zip', at = 'gh_8444.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + + watching_patterns = \ + ( + 'gbak:finishing, closing, and going home' + ,'gbak:adjusting the ONLINE and FORCED WRITES flags' + ) + watching_patterns = [ re.compile(p, re.IGNORECASE) for p in watching_patterns ] + + # restore _WITHOUT_ building indices: + act.gbak(switches=['-rep', '-i', '-verbint', '1000', str(tmp_fbk), 'localhost:' + str(tmp_fdb) ], combine_output = True, io_enc = locale.getpreferredencoding()) + print(f'Restore finished with retcode = {act.return_code}') + if act.return_code == 0: + # Print only interesting lines from gbak tail: + for line in act.clean_stdout.splitlines(): + for p in watching_patterns: + if p.search(line): + print(line) + else: + # If retcode !=0 then we can print the whole output of failed gbak: + for line in act.clean_stdout.splitlines(): + print(line) + act.reset() + + act.expected_stdout = """ + Restore finished with retcode = 0 + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From c16255b5d26f1548e8a3fd9b05371e7798543895 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 28 Feb 2025 01:14:04 +0300 Subject: [PATCH 0391/1064] Added compressed .fbk that is needed for test gh_8444_test.py --- files/gh_8444.zip | Bin 0 -> 4177423 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_8444.zip diff --git a/files/gh_8444.zip b/files/gh_8444.zip new file mode 100644 index 0000000000000000000000000000000000000000..564ceedc8bbe9cb0e16504878fa8b0f5712b71d2 GIT binary patch literal 4177423 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

1VhCk3m~M6};kTH4j5|AN!% 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

O7&- zE{G&+4c_x`#&eGZYx4S;@%lGFU6}=Pd5hPbAne15k`&YIk4|Fni1$N1&sx)BT7Rft zrXlhEH_f-@^5~77*p4Y#GHE{d7EZqQzzU(&i<2R7d*#9SlxP_=DC zM~EDBR5fn*$x{W;&>w6Pj-+*S=vUgCPPD?ka3=DOs@S-5z}xew9(Y<+)a9j0T0(IA zw}B5A=>xJ9SlmM^t7--cuPZw$-EG{cc6u__mAFHJZ`vDA$0KO*2wQ~s+(H$5UX|JTXS{II!|K!P`^yIU0R>-3JcuU-zm2pi7 zAw@J0eH`A`aa@SVk+1{xi7;Uj_!0YdHXs2D;~4+G9%z^0RGWp}mhSfcV47 zwe2JfgWt;Ly z18j*BED;1Q5nP;16M=My;FF19IqxZjV4MCx%P2UsJ*JSuhS!hG8;1mK*?(ltI43Gu zK=;aJBfE8}qe;|32X90j#3S#9ASlOjinwHo@Y9Ed@GY*`f-93sdU_WptXEL9TJQ}{ zb1vHJXDg2i$r3Zu8V&IKbyPPa7~s^JQ8I|kE=YkE zN12TF{3}jO;C&ggy+)vu?kiEk_^d<8@bN>2(xmjGxY@GUBL;#FcQu=;5J1QiNSuuof!ZIOofSTFS?r6A*)w9bUKhQK&W(^=>}pM~Cp(QBM*=o-JWVnDWw zx2zgm?N1&Mu8egNs1TKhzICjGuXSd}dsuK^QLresz^9&k!js-#qJ#}&JkNhg{aD<}ud zqwolMh@5!>j$Ggl62UB$9(%A!5FC&=Md@nS|JSdte6ZBNye}IzJ18bjIiBCWfE>oN zbMepd9Dnq?-;V3*!47uEUQ!Nwu(ipjwA}R&i%gvT$;iIKo@2ZshxfeRT9&U)q43#h zh2_LurMOMTT_kPDy-%i>u2I~gnC82w?(|HDiycZRT}!9kswQ{wlQDc2MiJkiyq8ea zN>aB?3)*NdndwdE=#gh#?p$ByrV(WqKRAQ$Y>2I}p;tpg*3?(0c%{0fwPXK7&V=vY853RAwg;J=DTorS5R31Z|hPVrH4}v>EOhFVOZa{26lpx9wvk(=C8blr9IYa~UBIISr z<|^NpP0@S=IR$weat3k(vIIE``4DmrvH~d~Ymg17lTf#zu0!2`x(PJ{Rf2j9Re@4a z0n~G-27(fTGJ;tI4-q^;AP`6dH3V-F)DZ*-8t)l1j&>ZgJz2

2Cv;v_>nbUN*^M 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 ^ZX+K1K{RFMWt7 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�}0A9yf;>&<)HKL2eEMn3$OY5Je%IFHmevd+H{A`urV| zt?g}O9PQgwztMX=#*gPvBjLxsW_`2-;8=4yHY&sYD@(|ZC78XQZ}DU)v>Fyv;LjY@e5;(_QmC+j(IkHN!%uvYY|W=`AAPQJNIlj&7|laYZ+JFex_ z>*6o;KiIB9r>fgs+%|T~c{QU@C*LXZL_}pdv)^ zl#z_e6!pG^BsTrdHtH^({MdLw3yfSPd$Cq1sVh!|oA2E^H{snSBs0qy+nmR}CPya-Rk8L%=rxpi@VdMQ&S4r3 z@VCj>x*GtZS;QO}DI74#viT*W+3xS=D)4Zry;xOxGzO}1Hwo?;s5nZmI=4gk`RuNo zdvES3MT$oFA8x(2`=ZZ%im8S6(h)Ts9Sa&8i`Vez7y$(0SnSNv(p(mS#Vi_&CQn4t zCBP8aWEnY(oY{7cn(}cTrO##Ejm1YIy(-K?`TK-(Z1=qwFId#3hfR-Kn)3%Px(}r# zEG(-z`OU-d`YX)9tFJmqE!XA-$OtwW ztw_BT5;#pp17yu^%b{-h??s>k0)0*snnOH^5yUlF3^}`uVJcr zoPL>4-T9e5pLFNQHsOAQHWgJNh82)0HT1(G2qx7BeRqc{g(s0pS zBS0xl*R~d=jI#2-q!k28TH{~^aj{q^0iUJYd$A2FoD(gI5Qj{+#hCDf(DTRxCovNV zK%+P7|5s;!IpCfkL$Nqwc9fLFbPNCJh@1Omvw~|WELf(f@GcU<3OF*UtwAQ+Un3JC z{2`X4U?SbGhd;#Z%Aljj_N=OH;Cs*o(>tV72Ojuoz1(H|44x~@aDh|!Vfwh_vz&VY z)^zz-zDatsEK9hjdENgfn_>tayDA&__5>vHmSXHd;e$w6Yg29b#U&=iyX^_sn5v$j z@>POJyocehK=N|`_3QEifvTL0eo`h?`lg?uvl@2s7k%qEy;#7cT&6KOdk1K3;HY#b z<7QW;d^xl4-2B-#$C!!E5|hfiS<0f;KKiHRr;o@N7wW+T>KHtN4^p>8-V}APalAPh zmDukIbpXzCdTCirL-dx?o%2#kZ^d#Itz5#&ZeLf(4tY;P1JYFrS&s5`m*_>>Mb3-~ zbXb|*OIg5Frc`@uU5sKavP6*9AFdw0%xVr(p9fB;1lZEsL5Dc5^f+e<&sbXw zH8+(VhA67_?}cSZe|CckC(MLP&sGQ`x{3K()WMOxpfLbb;`d1_<`sgR<_0kmKXpC2 zx{a_vzvMLk=wN|v4Iab|AqEmEaDS^O0Sblt?Gl2#|8BZy{?v6j;G=d{wBJQ*ByGe^ zR14ngZFfdm-5_Axrq_%*^;O2sE4%!tyx$`yT$W&s%9v36St6DJvhnDH3;vM?`Ts`D zP=F#FZ8OrxnE(#;wLXUPn?D})yGEtTNdor^%=|Vj7Fp310t`oXD7zo3y0UNO=-V`} zi-#93>g58p)v)&KvX;PtJ36Swpf2qM6u#+T7yjEgv-V2sb9bGb?0s;a7KFu51`+6x zZ`r^TYb3ghPo=yNzjjHa^M_XQTu0L#(PDDO8Qn_#9M<`4{Yeo8k%IY|PYq0M9OFez zC5|?J3%UJ*4RiD!g_W#{)i+K>B<4oQaz7tX&79F+v`_2xfhh^zWE`PhN|c)}DoE1H zm(RGp5vdm$H+HKJ!YY5ycv?{5^UdfeNgE>mxaS${>WL%%0Ag?rbI1uYV5q65 z;c-)Sze=;{44@m#Ej#F=GDCo!2rXl%bZAtp(`GSNEhWueaCQS^%*gr22jNOwTG|~; z)+|87jc>=hmODj`F?W7ibjNdp+KF%=xVM>RN*!lq8W()oU9N@{TbrhF!9DcH?%Kt4 zQFew(2p(h{%2{l9etGUkNs}EXUCn?-z0fS3N^q!^Oqt@GzPDGom2hTxkME1{K($LT z(|QaIN993qOab}gMMuA;nbv2m^fcLtJf7QQD$NqqtxJ|<%uZkRY@NyAuwS}k$1szY zDdzIJm3DghZT{_VYztyCWU(aLALj4Q9?^luMd(E26ve%&E)aW0Q*GH6-Q($7av>a+ z()FfV3N2ft1Hjy~1(-Ke>_EiYb-cgn+M7*UKY|oT$F{910TJUsD8!H3h%*+F-qv0d zBk0|lT?8E6$>6>;zZ91dK~3R3!1d1FFf|206D&BQBt`EW%*&Nv_Ep}Q9-o>%@bTfH zpJzX$CmybszW@@1dO&j&#z-CASf~?O)MVp!j`0HPR2n9b)i_{!UpNC4^wuY2=N(N zYC2L_xgXL_4x~`vKiAXmT?{nSx7pwz54&s;stZibwp(g4?h_)92e)VwMR1ohMF63ak zEF)(*0D>@hJrj6x49;@gnmwWK^ji2)``%d+S>-RX$DXDh=osRR8Z3av9$cI`TiR{x z(v59Tk;hDcer)E!8Xd%K9y4!AVY4j|AIbpnq1Tf8kl@t;LC?1qi6SJ30`0+fb?1s$ zJJco&yC{>~M$Bxizd1RNon`78^D45kY~&!R(K?&{Y^Wl^VJ#>usL1NSo9p7$YZRm3uN$ zD$_u$M$ZN*-5G6@7%FlLTjDLQZS*{ntG6W9*UZS>lj9o)TTl}wnf=sCzjqU4^BIc8 z&HP&rZC{Ce{qLRD3r}xRp5!oMpALZX%UeW?&@3lo?NIPhIE2pyAH9wk9;`3dt-#51 z^`lC_YGA{Q59s)tfR6tHh2WDSsk^SmZ&)*maJ;Jsd5NqSRg=z;Ns&2Hd7Y;%0i`%nNUydYMp&h-xQ>^eMk8IDuy;0bZ0smf?-J(x-fk4tF zrxWuRSUWDv43aWY>$Y_)cMPWYi9EYJH{2^v_bEFp)?aTzVA%1Q%tA&>cYsl>Ze4?F zPtr($;1`A!ceRnf=^C1DEZt~`yK!>6@2%lBCt(+}AR4jO!u-3=L5kWk3KNTcEKc@( z>_N|tTLCNgX{e*DXVlkZRcp75z-v*Ft$T{i7vz?>6b7Ut6e5I+DqblLa3tJRe>Zc- zW%RvDi&D^F^f0S5D$WU{otkcX`{R~aSE!+`V&21v+?DJ8Goi+<(&7RW&iueg)fF~9 zmu?WOnW`5|zLHvT#sFtXU02HS?0rr5rsE(Ten8<3ofMI6AasyM6JhLD{?U@eU(sk# z#NY>b7tjg9YyuiCwpax9>^}zw4iW4Sz+d{-BI%tKS(Lx@n>-9q^bIZ>1c4C96rMkb zp09ONfP+ak)TDQMsah5gnC+E3$F{~i)**Uh1xjT-*_&*RB5ZsP^ziB z(D25^<#gad)z2v~=LSZyVsqZvR#xWFAIr9aO6-?HYs9@kz~I0h{~mirMLrH1M$Odp z(vcSHjG9tksk)x4;oVo^0|kM&^kh{G=`dKRMwe+mr=OdDJf730H@(CfGqj)-3E@^U zzMUz#1^T#zq;{btZ;=h9?M1!|zPaz=8$;p{j`rjD$^D3&MXXh|4llf+4IQXLfUDMN zifxs_@yRqGVeR+!woP1>TI3_JO9hxNgBweD`iyBm@fL|oT@vLP3X0l(%($3DDCHVN&C4zPCc$2?B6%l-P+})^|Bt8K+OYJ`k5>q zS$;Kt&%x%F^_|1JDM@2yUr?BYZ#qn;c(GBKJkYKOaK!B8-KUYh6o_%SP4D>iQuCo0 zkHtHpoD-c)=k?P`+%n(zyBC_CH6KGAZvEx7K()Vu>HEo1i!Sa{=Q5O2)tMYxr*$&jb|!B;Jj zBA(MjV;36Y_~l(xg@fLSb7aEATUt$LIE{^LiX+?TCm*?~>z&ze8L6hEFclKXu1*W0 zUv?Y?K3U?z+UYpsrp3^ER90J_9H$|DyOefsR&kx^eb@^mj~^bnEsv1^--;=Qg%PM{ zzp;ey_uSt-fnw@K-eA*Nu;;E-m_}szv4HO=4Pg5!Q0rZL%@7)hu*849^&Y_Q4X<+`G%hl+099OFGTW z&PoR}ST)Y@w|HsLE_hg14%rk-+06@OPudS9s!(a0Ov(D>I`_Lgog2S}P?mFb)r@PF z`Y7tbnEBJ9o|G3<7K-+C+(oAJ09%uN`DncVm0(>uxjqXJ4l^Wq#0L0D8yXHSXlw3( z;8%b!coIwO z|B2Fq5rDYy1-Onr4I6cl4gUjDf=@tJ`%WAw0a|nHtgWZ-k(fTRRQvdt#&WmcJ%r48 zwFYqa21jU}U*CVl{6>&g+&KyPupd&mu6OuyEZl55e{{T9ZOU3QLty@hlF9-2tL;g! zKnJ6)Q`;Nx==!!4v0b%Fhi&Gn)2C$nZ%|w-lFA`FuI?8amFed8@EHr+?D50G*;Ef$ zr7p4slMBvdKkoF=T^e`5G}@Se&`EOiOjLS`|G-?R``w@6nUr*P)Re$kWx_HIiBs)y zv`WkD&~z1%x^efu%Cz2Vp4QKUbAZk(bxDVztPnaj@gse4A01;zOGJ0cK@N+BF{@$q z99I0y(mif4@T=u83yDt4SQ2Ue@lddsr;c?Xmk?4x-lr;0ZxPiBapaB!65HTkWe25#^CeSS*L>vHjw=viI1dHul zkdNo7L|r~!6nO4edTGT@@h#WPTtjP-DP;aUqG=Vi1Tt4g?~13`NTj zP|aRrK~Fet;|8~=|2MLlOti^Bqn-xW4zb98g)h)_Tstd~Vffxko}x5$@{a1l^_C3F zA36HFmGs|t1OsM^bcd3a+}#qii6T7w_!<*Mpkkq$#pN*|%_PBzhi9ZMgj^UXJr=c& zYaFSl;s*&qf(G{>$FjYV79R7-u%<3WP{Z-`lcG+y>4D(|_g5oo!xbS7y))!dirKjd zV`r45%XJjz?EKVy=B)gBMEaYBmkxNOkW)6)vL=GWWFt4AS??_-@_+P}$y6S&)UCAV zL13=0A;S4ZxdZSxJDr0>Vn5;5rcnV?P1dc!kDwcWe3wUbe+5F($+Rzez6g8O}J8ClQE*kHVS3He5b_Y>K{@i4N5O2590SBB|7zp3L z3xw~t_P4j#h2Rco`9TyjmIWJMv4Xaw6D!AyQ5D7o)hiy9C zE_=BT1Vyu9M}}pwz_4M2gZE3V9U{PtTbcTheo$@W;cOxEIz%koQCp!sj2=fx`HXrPf9wt6G1VH463VL&hs^3qOlobd|=d1>oD zG?iLODfI9k@8(BzEbrK>Fvc1Gz9N~_vrD|=PpVyBO*@4*%(OUax7kb_&dYTWPwS%} zv#k{1cX4>kCf@B1pX)Ctq1WMapMA)5wE}XzyTAp=YK9=in@f*KqdJN(vseP z82=aRp45+}T7@2xrXKgj&YP<22A-`CXSICpd*8aUdyC4Gof2PyZ*lV^MT~Ey13`_3 zM^xEoc7jMWz;%MM9??PUFK8ZOIIthx+{%sp6Mmn^H0w+H;cxq^bIPKY6WPw6&4bV`gXQ|LSHvhD^M<(nVb2ib! z4Y2Zw1;ILD^&a1WMf>LN>bm2VeT)8=rrBy_BL`V)M&;Pyv@pyl;;Zl)A>ScJq;Hn*ZVtZy=chu1@0(BkY zGpgB?_1RiUHhehotv!Q_WXaOq55CzY*@M8Ei?UJZ0ryj}fS z9{!_t9PU*MRWs&7#EQXZHHlVntYS7U&Z8T+p)HfpUV{ew$A=5Vi%5v4DL%ha`*&Hk zCjIcHorIzRgFqZ>Kj-mz=3S|){BC{Cub=s5>Nby%9&lh&f9(zj%Nlkh# zED_r+S>7tqxabpbXf0fvV8Dn!_u^T=tcfc;N^n#*xCI00${Ui~6gynoU#LMzWVv4F zIhIi!pgB9C3=cYq`kdc}mssdG_34gA=8?`_bd=JulxDh3umdXUnwxXhU_U#_34k1P4uP z)$j63HAx+}UkD4)y&~WK$!(q~cI1_ql4pO0<0KoKe^~S*u`|&w?2-Nb;gyeXMz_9G ze#`I4agsxEL^CJj+DNvPb7qSIzX5luce(!=^oSy^ixG#P*fcg79&ac#O5K}uW+mkN zOr}wr^a7oe$PmVsdREsS=9nu~MERJq$!?{N?>R4SE=9-+3~f%0fiHq{@c;jH*foUh zFv*;Xw5Iqyr1ui&$0~_Ick1^^9wADHhC-ZH7Z2j^HwIHN;s%?8AV@nmcuFUjW(!es zd*0fXfM3{+LH787W1js-l20H*#ZH8Y-;P5}prQ)SpiR%qAq&isTO}^aQ=6Gh0V}_W> z!&5PX23j$%mO_(FG&0jf94xQzDYV)v05TsJyl083jDF2p6?NQgy!AG3gl9*ywbGub z#OSBvD*WHAlt`f(yz_SNBda|NgEbNyeQTLwX2yyK)(0(Y-eJHUtuFvc|LK0BS2m_l}Tj&K6Xe^(`HU7!Y`c@Co|G z{DBh05E)=41S}oyz^#P5Bs7wDu`hly?iW6-$E=rejvDUZ>p*9}xAiH__1?l$6qB3Z z!lTo4xICKmqk1(A{nv?scf$G8=>QXlb|C$@xt$q3GU#g_|E!P4hi8o*9nPZ3Pd}Bp z>%4epAtPEP+>GYF7js`S{`lYAc z0rmC8{qo)64ZLL<-sI17qsN!(zD$6?8lJLTvf3g{C30#a50w+C^YpLh3FR}ZP#WQsKMJy8f(RLGRSrQ;TCmU8Z(kDFS<2>D9Zjhg;&7%;y( z815fFPthhd;1%y{9bp|=dhgKP>Y1U59t?0TSILxVUefjc=_CIV{unPjz-rk%D9#4`+Y|ij zRf5eUp=@f@dK)l!XTALuQ7QThpK#+sB%V;B z>maZJ!~a?x8FWGX#{7!;SXVTi@i8&8>6%QKSMT~GoS92*}r|%Br)kp)P?xbR6Vh+l;(b_#q_mT zli;anf;EhsAi;T8T8ip*oHi$<#hV^}S8Olse%x!@Vedm1pSF?b%msfsU8a}Qp$X(d z(FFVw`SIP4qTQNO{#usOJYpgyDkReQyuK7+Ge#@kbPPEc(U0wY7H@YTactx*!0Gx>Lk>ZFQVXRJNZO zkP}~u92D0|5es_jUr_tOq4TlBknx#7v5AkiaV;GDVlK@LlGRb-E#)v{6Hfjo6Dlxk zllq~Vr^6M=2lnub#kGK(Hj*-|BDBs=`xc!*pagOdWu#oKf`PWR z%{Lb0I&gJa2^hY@^`falf!TaP>8p!Z`I5fX@Z%|O3z2AFNPLj&LWV+0T)k3qTzByF zJ^@r;k@WNbh^zB;kkU!?!sKz*p>12zH?8b4{af46e?}@)gWnVjix9WJc@}S{3!pc4I3B6k(^MKcgtCz)<4b_4)A)@TC+2GhU51fFN@=Ym!UPfb!su zeLROkMq5iH{mH6(qYu3%<+a{Uw!~v0Q?;-6a{|@w1Cci({Kc~*&-L$;okyx)Y_{Ph zZI31p@|PZ8IWuru=Glj@_H*v`EuL0WcUg42`%k%6Ae3+(_US&a zgg~f@4Qxe-cCEVrH^MaFAKy@804~Ha4R{d$7fb`e1K|dl211M-vhy35sr48;Bw%7@ z3P60niGn2L(EMI%`+UewjlA3lg~Bkq5l(pK`E{+$SEmt7Btk!n{RCK~W}&bl-oxy> z*Uw1DuSzrhk*uHS4?>vn9bi`9C2CRNt%(gBxiL*aA&#|X z#uSHTOyy|rQob3p*X%53{w8+uqY-U8n=Oeg<5MbUh=10mZ7)%zV{))jj>>mZ+&3;a*%0$|^VeB~QBR=OqQ>LM~u%4b(g%CnJ8 zxqLQU=Bi_@OPlqYuw51ko9N6c&rTGOj2k?}HdRbkg|={q4`ci0n7HH-?h)E)=sO$I zg~Cs_-Z+lT_&Wp}a*akwLZS&t?j~YXaK{;I+yXt$Ao6cTJYxU2BhVpn~hSQMF($uA8xU zcEn?6WkdvCWJ%)LzTYA3L*deI!7TH!NBL+VJgw0vv*T zerA4IAcJ!_;U0!+5O8ZJVC;h_j-IdUrb$4Im$WLBZwEqo(q;L3Pp(eOzzu&;pL%_4 z=XZ5@1ZV8eA2`3agRp1_;XJO11RUO<5ma;w@QBBT78nvLkjS4g*n0pO0Q9G>nw;Y^b=H@2-0JZI8PDy<`VB@10FMkdTtk%H2w-r5%6qJAxKlO3y0)jsthi}ZL`EECdx7ckY^mDm<6(+o;tn~% zp`LU*?Xrz$&Y{>)KnxpHp1H^{goqPyc#j!5sP#i;AMZ}i!#E@*4uFiBk$&%K)KBh? zZ_>%G4l=U4>5maKYN-|VISiBb|M`Hn{M2#3Q?ftmOtueJ;5`oUFRpT<9{v=6v=?r` zZTYcVXsp*3L6XHK?gjYU{`8HnxO2qLul#a1Je6A|?my@|O_ z{N>C5lfnVYya`IAmudp)!5mJW+`kDF>JdCeuM*z7?Ln34Ti>)t4I9SS+fZ}x*f)fp z#8&E&J$E$)RO&Hh&b|hv?KRu0X2hXxm`F9(3+YYjGC7Za%H#vJGZ(yw8=B|>zAs9)Hqruhy;6K=40)HnveB4k>Nj;n3I|Vd zCpVq7-r!6RONmx$#9`levO*pQC!cpZQ2IE9~u-C*X8o{&FJY@5ABbHx}kg5>IE-%^b&JE?S5kxpAaB$Yh1EP)KApfS=0sG>hvTQAK zd1)8ZU)wjn_90aQ=A(bo^_6IP4tgRE zGnwV?^irQL^+RBpA1Ob}C<5-5j_3(NRLb*7a$LBO`puPUqQlC)Sj3h$Y$WYjxJbMk zBZfjIOvJ>q+(ZX$$zx?v$-bnme9ugeyc2??90e<_Ml zwq*9j?Q2BeG0Svjllh7qaF;k%H&OrO-YvrY zid4~pV>o^S(3r2YPhU~(gKf2nEdr5!%Th9c1^ky}iTK=GAOmwl0*Aj~X~gK!9H3Q_ zB|?aQ(V2x25SZpcwB379Ex_qPgOKG9x*Z4ClYs=B9)`kd54*A3a^ur}IDdL9ggbOb zKatJhDc{AUUW7809VE;GLaeGMl&=^6Sr&x|{qWbM0tamYiG+B;KW!D$Yra1KFMjbK zjz8TnZscB*t+DGs=w`28zC;UAj(hR9#ZLeDK$nq8R)S`ETc4HbCEC#VGc)rFzXzk% z?#6-OH!4!j6VnZ~vlrxh?+0%${&fN0BkWOrqk7dV6N$*y1o{9^{djuzL8ihX?iZ7i z+PHmXl$w^z%vnUDBoC;|X*^~mkL>;Q%sCf$-lmzKcD0OXr{D@qjjc4NE=-PW&9}Dk z)AzLKtFqvkz13P*Qt@7*j!(sR=v%0!O8w!mARWJ;3GV$~y`r?eRLEZjw1p?#rvvJ> z$0psC*@PlNwv+@eG;&5zUM~(Y^ImRGPo`_!-W}DcaqXjarz}%j1hPcW$fbzh^Ze>K z?m1{Ya3&a0#wNNcpfKjr9y8GMyuS5rMZcB|54=!v?k59q@yOPSe36ZgRoBBhuhJAi z*;6?3Y~YoORbvi4i_~Y~sg~!`W&9E^>V>}sUr*P;#`S|{)5_`0df3tN^K@keF(d_N zC|uNog?TZ5ab+&D($x8@l|KI*Z~`a~5E|4$0IM?yU^VuU1|^<0`MR(iEKp&vOX`wl zqF0V>Fyz*^8>DR?jK`b71<?L!XhKOGa9#1a=M z{;meL+26VE7hZ5zGD=(`BK)*vywAp+JeCF0eTQA<+I9$Jn zx#?8lo|yS%znT=#8Kp}yKRWx^75V*RjouYdI(mr9 z@fS}fh<4W5fZy=Wzm7Z9iv-!Zt2G(8UGID&7_4$LOX!K(OLif)d&pBK4R%G#g_Ks9 z?3vEW#4+;*_O5r6SDh2nXCzIs8;7lG@28?>1$i4?XDxbH4OczSqgO3f6gV*ZR+qz-pr_a8sxx(k|HggZxjo?=?P9>2ONs$HT7= zWe-DMB(^+w2`5Eg>0alCqNE+*Zx2tY5!|Y`XYYM|0j#+DDmU$GScUf?$Ecj)pWcTE zaob>q(@!o!@Uxh zmsN@##P6+sM>*#ow$l9h9a;M0_ci|%=mbE7$kHYlD4MMszV*TOuyWzI+GpJ9Zky3u zHG33L<-zk%51rKh#j9T|RKKAV=?t9f13>9leTH?1wwq~Xf>Jnb@}Oom>R+R_^#adLmln{{_a~EpQLX^ z+Xug|t?wLumD~+G&RM3x{@5`>F`<3*aYU-1Gr#7!ct&u5CoP!U&&H`l=XEFB;bh6eZ_msm)l_olJvcM^W(v@u zA~dg6PKJ<*#Jqqr^k7D`>P4wfVr;9AuY=jApNeni2&KF@+IDKPJQ5s*mf#rZnJ)ceFz*KxltXbZ z0JHAk<2_fICb)tOU3aQLaIv48cjiv!55!ytp!=76-ZZGKgZV8K#9;yjacUcsC{hsH z7uC@M;`?G<{$}eXFkrCX(v11GP_<&GEz9 zK|q&3{WP4txJF8Q=ya&nbsvp7RywGmudP}dCT$~ zIwXmd7^A=!z+Ij{f9|feETfer1qk?RL~8)?%@%9{OG(2cQ2vY^0p5wpdg9l=X5>awB*PB(zI*^0K zMFcJf_V*)(CKOCRojec`r`?g(I$lwgr?v#|x=Wot^Dq?&&r5$3!IX&DegZIHkRqeX z{<-4Q?x76inBrqi5vw8^SmnkUd{^d=z6T>+&X38COi4n?uuXYE8aWUVu1S+1fNL`A zs|F?1_{i)J(#XZkUif%pR6orcLr>ol##Lq!=c5|Ae~%SBaDd?x9gm-Xi@OAmLQAX! z&umPAKvrZ)cq-ys_0YFYO;w(Q5^b9x*E@a9Q86;y6rr4e!Q7NkryGIi=nU{g$jH()%H?%5-n&6r z7AH#Mr=3q)ENB;zWmHPH^!?9X3iDG^s+-{|DA${%Q9C^2BR)o*pG4Oaj+)j`$59F} zN?*pEX>nc-EN7l-G$+jNNXs^u{|Wp$1-Kd{oh+$D*ZU`eB@u_Sd9JZiCAu{cTtfbf zdxN;||EB(n3}Ev&5<>j{nWJONWAAO&zvx1<>7V%#tYtA1-D2S(uj)-LgSaX_z4T21 z!by-n!&B^A^7!_oK(RS}>+i$b5KkjM9ua5}9OYD(Qr&NhXR-KkF1vYI^?=pUwWVBw zaH8R!zPd?^?+>7ynOgYj0nzbWuE@pf{RAo%kdL$LuJl}|Pk$BFufzT5NX0IAm7y7nD<~tofFBe@8 zZ+NRrHSkVCmWa%mN;s}@<-^s;&3x5Qy6&a3aph_Xj4+b|=D|KC>sS0C7b~qyEBmIM zQKHcUNq$8`6WsOONkzF86U}D_U+S|2q9+fyU3|s=>4oIz;TXxhQHyHPdp+g9`dbWv zEg~e^(8^pMa!?{eOoNS0s2op^B)XHkydp0^%0pG+CA{n|)<0=@(vDQ(+^j~Q+zqwB zI0j9dCt)wCVk6J^DFoSc_UWFRPAx+}nyKs1Td?nBq-!G;#!Ciwks=%7po#h_!S7Mc!pvl zQ^x-xope~I^9IJ$ptQroP*8o&8aRiA|EvKFgCXWaWEno>u}v{7<;O5w3G&}0Rm67* zk9X+!2PATtG`gDi1s=6z{$v-Sab>;W?jl2X5e)$-dh}-shK?gB1;@sKn;@I7)A)KG zflSB#b(33|f$}4m>n%tv5dX7L;IX;yo`>NSP&vmUPOF{beDmVUbso3%-lTa zuPCPdDC!tTQdRqWG(+>J-SHj_x+9G)z76;*DXfDrMg7dJ^&LGEZG_4VpY6D(47?D) z1XwX2I{49S89M*SnU|oVXGaDe^Yh2Q=RHK68P{&*UP-05CKU(~(lkHr)zK*BzGqLc zUW|GaB>s0`WKOUr=UdNN8()T$r~l<2fPFSWZ3Rgeyj0>YuDah;b-sVtlVy>?YeL5y zY+~r+-lY3K|r9CR%o@T}ZS?{Szlk z+Y;x>B3z_BRRm5zZqRzKK9S7Ss5TM~Tpj~iqPZ?s+of6UcN^3#_Y(-@Il#Tw1E~}} z&Eq4gR3tUgc~(iO)mMVYYRbezG>tD}^e$}`LR{`c44oUw)524WmaF2cyJK#TNXRRJ zp|8z}*f9H2+QL#O%sy4Ggywb52vP*oAH~s`U5iFd!ulct$fALQk z2jP-j!ZmP^{(cc*qaYt*O%DQtnJ~Q!x_~E$+Ca=XC^{5yCL*Dq^O_9YGr>2pDAMt- z+hM+ifxSlp2al*LgoVZ22-y$a@Eb1t_r1sV0AO>u1`+!U{%aLt3P^1n#81v^2(!J| zQLuOCgDVG5Q=70Dn`x;Tx7ly|*Se9@`@uwi@4k@b`X!Zws$ z@Owj9VS3(Ws`} zovvUsR4lYiLo)SMTgaI3bc$f13cOeUC#vYk7)zOE+S6Q<>JOo8X(>T*Q*0AdLpgo& zL-KZw=i4$H_2Uo@wQU!Q%Tce}G|cZ68L_?ovWd$~XFW*cu#QcVy}Way_u;C;nBu#M z{9B}*$?K?p`6yZU;zr+ZluBM3NUoFrV+%XWzmZRp=?uqGNX?41H^KaN4?o=~d~{?Z zx_6`SI|54>%s&>7$@wE|)ch&_1b0dPH?D%KTUX0O1QniB`+xC#W(OcoEBuD>)jD>^EmLdmD-irX3()=grYliJC%gow_ER=>9!82 z?LV%fbgiS0M198W6;`$XFE%Pl=fSt!TCKu}MnhgUXLr+VQ@3{}Ak`MP=3EY3Jtuz2 z1FGa?o!W}LH^%I;r#oiqlFJ>zJ{nFj1PpvEVQpC&IjB5vDi{I9_#jg)ql{8` zDlf3l73b5lXX`PS7Ud$1jn~Y*%idZYWMe1ZhtZ4v)R&yI_YUfKwMn3pdOm+ilGdJ? zD}=PkHv`%`FZo1meLeqwh8Q#}GCt?;)6EcHJ8RTkE~6{+yaYABbbm^TNVb%=Z43db(fO8s3 zmtO_B?=_<-;d^`Vl`d5&)vgmsk`+7;)1Hw1aM6Er=a3NO__J64*rr1m<+t@D>b6kT zcb%ffjQI{>Pckfi=t;;MqfKp3(sNGSWl=s_TzUcIdZis@#Qtt?6z<;A7vt1b80#T$ z!z}G9s-tK!Gae4YUEmgq0tu{%X6a0b`shKPa=)|>R1>CdBrGCBEt+YQ<;}6V^?_xR zd)?6ChqXiUZ28MWZ_~Upq6zb&y+PYc=`ir-S^PtonJpy~yiTAw0a|ng{$)Cjg@OHv(7KeLVech` zxHiHu*BxT?V-aTNTK(Nx1UBTw8Qd~9&|f;}XR(t`;m0YJdD76{kgT+T5_^h!VJE+f zS-eOsIwIlySYl!8gll8`W})re*+R9x{#c`2tWe`H6%i60cnL4yG-NEh>Cag)A+{HT z`a5*s?*tIlfXDHU4gDM)Y|+8j6yju)-tUp$HsL$defAdBBl|m_(Cz1rH(pE}dYrPU z?^5=a_UrGQQ4h_}Vr$P^K#4C|vvi6&9gJFG@+2a7xcH-eSHszpG9oS>*2m~OC+bYI zwfx>eC8oM{y>Ly0Li}3#Vx5vv@xWV0BrOM7^1U_R(E$X#)T0$%54@y`$^9rb^zuJ5l>Rf(6e@$3`~M_Zn?=F~7DO?H>o zCnbppsOY80D*tsp)v{a@-Z`8U5u2D=t{0DR2+*LLzRrQc^b9AWPN{LE)=dRE07bU# zjeD=ZwvBraDo-BeFGGlj91SScdeUxfb{Bjl;H`Rk&%a(zljvE0zL3&%-RnuKak}e6 zwvj$#F0Efu^x1%Kjv;t>POuxrBugW1E0i?C~&EWfMr zxw^@+4C0^9-1%WcCrj5d5kj{LArkw5`Tnf5P*zFhaQy+Xa=X`U*?4(ZEh8yUCXC?+ zZ1iTK+<5l`y+f=^#z&AoSLmyx)C;h4wn7Sqp55usxuh-Fa9<*1FgRrw(TErPy{j9@ zGGFZf7vwtHhy_H--93}$>)o0yrXnE0OUbza?Q)x~IdE8x}OYO3@ zw>+Wp;Z_dNO$lzhlJRJJ^pCmpkG@qluW_E+1{8_Q@bU3MyvP0*l84iGlNY9>?~e9S z*L>aP7B|T?SBl#1N5SA-N<-}#`R|AMbNvG^a@Oq^sViWp8Jmn`DA6iU?Q9NScN_WkRegKO~`t5~CF<(Vp|Fl(U{b`-jjR0au?t|-3cHM$?Y0k=(wov2 z|BF2jYY<{@(9#NT8KV#IqtoS^i`{n#jF?+jUT^$b=wh6>u%gJAZFbKML{>%Fkag_01cY_Mw=sB_waNHNt$24$713J}@A77XeA+ZU z3aLc}ipLNE>8vj05hb=IC%Hgz;O-lx5mYru#~RfHZWqhg+b@$_;=WnhHL1ncvsfYn zYI=$}R4rzH1ooZrwh=xjX!1|`ZNI{_9CK68a?Kqk3Hz_oBzS$jncIWwaYmj{*)tcd zYQyKJgt>RSHFv9L0-1cDh;p!gA*Z-6Z#*WivGvIXD z0)&D+qyi_t|DPY{YEVU>I|I_+npO|CFFPvG<%>tdxE|e zn0OqjeszV8Z%dlwCjSgoGv*x-_k{!9*)8&zPtU)MWg_c=bIJu!FV2<>tJ3Q|=$Sj@5x!0Cz_Oe-lW5K@8mVZ?<(i}#33o|Fiz^jso z0Yv|w!2!ofGul2yK0(o+-?c$R)`T%7CFKY*_zk3dzTJ4%`J}2IK4KV$=t+rskolgw`V|WK;a}k1BPnge#~rZaZ$13+t}%*3a09a z;?&esbcuq_luLwuO{{8f_#m3GK5{TiV$X$iB|hyQHu`rmK_l`VYE>cbe0n?>wwe1k zC8vKeeNuc%mS>BOz%<=A^RcsuNTLf%;yC}L%@-ZR5#FgKjc&bry1hI#CY*%qssan$ z&fEs7HHN_wLF|(VG|ym+6O)qpB|N28 zvS;c9zA1651V41JIaLM5o&eHYI`NdwkBS*vSRzs z@u-M%(sCwlCJ{ zvbr9mZfXM>ZRVoZ(`NR%r;ESJ%eWw?^mu;`m6>Mi`SI}rR&`!?&LA|ib%Y82onB9( z0%BED2RPInBfKJV!}u_DVIc^OpNN?^$7!dZqANsm>Sv6=fThLl+GWKT z!qM%Cu4@;N-LaXks>?VpQ%lUV%j>bfavHbLInfcGw09}ewoj`D>Cqw4MLk;Kv35~s z%B$deaf@PVtTe7!Gh}!Cyoey{JOBbxd_{F$p8&|D*ue`jDe^XhOp5MBxUK1( z-REMb?ok?sq(PY!f3fL_lA6J7_A*l;Nn9d_G|nMP+yzJi)1#*^RI?}*vkVq8)_;V! z*6jNs6vDqm<3_97MbUT#ZF4TbFQNi17Zn`h?xCmj`cqm890h!LTOH2w@4eObkDI!621L8 zd1Q}z5>Jk|Pb2PyR9y0TTpJd0D7UJbt+|pzSPFO)>ZSHsO;o4#wH&q=su2j$qZ=@< z0;yeV9R0->;Q_iogJJ2?fv)MShgR4uLDAHu>Kg(P4YdDnk#V^Iw8l9Cbr!fH-Pi=x zVvU2cz(OzPrU-3BXP8QZzK_3@6W$dwZfGhhO{Z_NN8u=Es zOf$WBbwPs!pTFnN(Pp#Z!Ve7(WY|?G-Uch^$7bHwoZGybnKcvC-b2D+PeVFYgB5xG z=i>b;1kip>|Of$+N8Nb^Jp)K;y`x*zC^7qtF~1X_8huOX(6XN?wK3RO$K<)Aym(Lbk2k z!{L`hU_h*#aG-^*xwyD$a`@w%-Xj++D>du8UZPXW5|dEO)e`9%R4uM??IYEy3CELA z*3gO?NzYapV?Mi733ng6CvU?fD>m{V%9CU8&yr4oXTe4(sHx|g0$MnhikQV|xQM=@2G&5ZvnzQcQQbi>@$!*Yz%s=g$eBL*!059IpVa+~2W3i$Xd$r;0 z`4f-jS$fW*U7aL3J9)!{>FIAdhui$zhZAw+$s_1(nCN@iDm?a_sl)6`$hD&Oud{o_ z!s%NK7Y#&LqpS9%R8LcfDJf6)v<`FAF%Oo|)3FSGmkD~^R}>IGcrn2Iv`avN#8lC_ z;wFX)y_5r~b&-}e4w~Wh`+KCOljOz(P@_lSmStT$Jtz~C0~{4e5(!Ezp|j07cYZ`9 zgldJsm41#)2o;McpT+oSzvz;i%Cq3akT+Fnrs;ci=&@E@koW64;M0X0q|~M48)H72 zxtF8add~L?mTk(zq?L4Ad3%ng-niPpnXmAsEY8vVj6PY{Y>h)~@RBJrvrOb#%l>-~ z>BOa#HLXaj&(PA1(8ZaNUGp2ExhMaXUZQOAQZn{gf)}WM2iKBdzcqFr*TH4j2A5Yy zP!=)>f^>5DoM5ItvO6DaFSFlnv+gbfQnM6EuCNDWvMrYyxXjxxkz{gWc%7Ecp@UA> zDQ3Y|Nb}M+#cKnYh5~(N5IxeULuxdq;sc#3Clc&UgAeweM>ecHGeqZ`or)D}Iu&`u zR2+4*hdQ}io12cmsUxmY#if(^qCjO{XmZ%~)d5?V8uu)8f_^Z9Z!8nx6zyOZ+ z;s6_MWAUF7GN?f1)55NPV|k9Lp^Pkzts*inP0~N+J1A*Jrz=TX@kL9qP)eAL+?o}- z(Wd?(_(M^XKwkbt+p7YWGMoLKwYrZvn^13yDsSS3p7^+QII!#n{8_9=M{cyM@66k{ zzU0C*vq2A=zUHg;sAna*oc!Ff#!pAp7mskBHS!(G}& zLmn)o;oZ-j(Qr3yu&2Sg(xrTtsQ_hx$|N^~-il#m4FbU<^ zn>RrwSMJi9pump@-vJfhOi{~ytcnjRPDq$F0d|L2F|`Z`LrXr=B=yc`5(M-Et#^^5 z2aQ>jW3kTPBO+s8aqT$x6OM~IJ7Mx;Z}S&Cv;CS{Rni+s6-j?T*j-e2I7!q`gduCv zPRI5svZAj>!dAM)w<*lp%A?Qr)X;cKU%P1<{~ofM<4}dQKu}?gC*Ouz&Wxc<-BH4h zP3xYzm8JB~Tgc62T5QFl#h8&M+x8+#=c&VBfJTVgif%fW&3oCInIGs}qx9*}$9 zdf-9@cZC-y0c1UJQ4KLv+g4K4dp|C=UY@$Ao8w;Mowhn**u!-P?fIW3{u{h4Q7}ee z)c@+W!$DN=6pkz1K-*C;~(Yf&n(1BoS+inPZ;Dk^!nky7;HwcobS>vLZ!kqU=3#F zCC9#_QodJNnfdBkEVIxqs`@kc=+huQAHnBF!@>pP8GZg57jppT-VI<`4)pey_rf0B z^`Rsa-$^@At?%Zx&r~U7PJ;q9f3to;yqLTF4~wp)v0o5NA9Qg#Rsrfu_7pvhh&=O4 zz3rKVuQOCUh(maHAfJJTNqa-SUW3h6+|A`SWZ)Ml ze}9W6#DoHA)zlFt=r=YNT4{b7*{oV}Do>N=RfuS$6}l}|`Skf`k|DlSR(u}nEt<7` z!x)RILNn7zDi*%zDa|pd0;>93g|}^7?M{eN!tZ@LFW5CIYZObHN23$DqlNU7z#I}Q zXg1V_9((3km6tv6;4bv9 zwQ-NT;7Nsz&|5T^8*di<9z7R+v#uke6J`v zn8YakG@s{zkbhRi&H67={X4HmKlgZ#b0FHTEUEXdugPMpc4N_GKP$+3vQCAZqf=dxx8NC1&IpjwkX|hGwGMSl zQ|CaeE2=H+b~q9va%SCls*-W1E%}(#bij0&(m2&JOVOfQVsrBZsJj<4pebSk*jkzK zGI0q%N7q7>fVdRA9;%%>Uf*&M9?LW7NK(mZRnb4DzLPsf*S5n_+6EEHtL{s_+yH0K2R#> zyHAmm?5V_8rb-1xuD7f=AV$co9riE>4LL|mU322_-gF50XxGS?1MBSP9c8tRY)ec; zu&AA_Rj+0xwU4FKk{4Q6KRG_gL_f&=qCAcjOA2A*`E0RMM-YiIkd3ISBqWiWt2%k2 znV&Z=Gok{aajtJ?A3XdqJiwf~$Lkn^v;OBqXNLt3S8uy4)m+CqBQ=y@@9S!#iyvoFf#QPex^I}^ZU!5v0wb|d_9YMmKGxOCxq>>Kz^85P) zHw1)rtt&D7bmk!EsA?r0V8zvz^_ZNmX=8{pu=ElUt}fI4W>P(I(_zTToC`}{A}|UO zH@jwtu0&{Y_b+<;a{&KSnj^+~|C)*69=5<#0iy&`>;|!2(_4kCpx|=5eqL1_cc^kZ zexNIbjwkyHpauC`1dEa+rBuBoIq>c0jw`qyt>{98z3o4d0JS1y=7h}tZ+3-qoy8p% zy%Z2w@@pzQ_LpH@vLcxs9##CXpr21OM1d?20&3A*+6>4=O#?GhceDtamTA zX~XP~qCqp6Y-DS7-r-I*F;Y9tluv_Cice zc1YNodidLE4*I4>mgpe`R4iz!WSzUMR3bQYKsuLb!={1eJL$(A`DlC-7%&|)(_l%_ z7L-ODQ=PSyx!CQWQ|MwF&BYjYUwr18@2@DO9$=zPsTD^xzAXuXLh)X`8{b=hEA5p( z2*qOMZewp4+K!!6I=WMU(E34@iy{b8s{^`^q%+WybMpnU$h(P?)&Ja9& zk%D6dp0GOYEr9U7pfXm=ZeQ=Z-MpIMP(hkS(%%|YO7|8ByTF7gcK+q6Vf}QpCV417C7}q@ zWgS)INaYq{ZAV^MEyG*>N&K7ZzE@a8mq3TY%j=rl=2-TC|>G~bo9Ncqz%Y$Puv-SXrb8v^N8 zJ}!Ab71EgfE8j6BId(`HN?yTK98zV7CY^hhhOb@5@0EV8mqlWN(hPguC%25NzpLvD zw}ksKTcuBjjZMEI+!1~H7w5%$Y(+2LRqFd7pNb_3V^%>cpb;*eTVSDo0N$0yx6F*4 zf3bPP%k%4IgPrWRB+ff(7&lq_? z%(|FqT$z)N+oZfkkD21%oox)!aObsAU1D5dLOgqWxr^_2`3Q4m%Kk|P~8yBHF7|3>`+p{XR){A2sSAXQ`k1z&$P9%5_= z2j~wNF#$`P?+*y${2<0Fw%1(0*{&uJz0ZZ%Ta7N_O1IxqWZ<&cr=*)COCb zd5_2$Fz!2l?alXZ0y`{>OFnlDA3xciF_!rms#>;*s^XcO5rw-!g4?4g{h{KLT{c1<0_ceKaaVx3+V z4tRme3ks;nni7-nS*JpMrDQ(a*{A~7{HeHt;#n$-@fmLCx^$;*RjMl4(C)J_b-H#h zCYjl3Q@vBrEM33eBMOhXPsiwn1|wf)$s}1yNhO=GYKb%s@JoEk0^aYNr8M{M2xZu5 z)zkBX&CFGC`bpK46v*1rlz7d8eU_$dLZ-9qzPfgF?FIDb1n{*F$Ame+i{EO08n!WG zOLb)s;+cE5+jQIMAo5ZKc_06H=dWMu>_s(Cns=TwS9na3!u-f_xYpIrs@Ac#2_$(O zkCmh-R;0K}dRMMYf#NDN0Rl6+xCySnGIsptQbtY@4c1kju#odwmgjHD_+L$D{8*Ml zT*Gw61103d*z12pD}I9m&`d8<*+&ILqdc15bAMMO(a8X?wvJDa;(GRe^>5Eo5P@lorSp9Q`(PHRzwxEgd-r`&0RWlCsVqpcWATF$FBmBEuR=*(-3)oqX9H4~4*_p38A4-ZVgUrl- zlx}t#xNGU>ra|nY3&jiRDJVgD3cdcwZAYxlq2#G|Di+s^VX#?r6Lk9L^lW+*8Fx_TrOoF$nv}>+&^IE`o#KEn%zY@9Yu-04lhbZ4w~~wZ`)&AS z+CoJxT10Eu7R|}($&LYDOsN>DCx@ZrS!%IW*}UsdupJsT{ny*1Treqo*R?~uu@RBv z-&k8tg#W{2vw`B#DGBkZ*epx4Jr6f=ZG!4jrCaR_{#+wAJD*|F3VP&8Jfg2v}q~sk)VmyCkeBNWXh{MID7Vbq^${}7(LiEcsa%U z#GsxSg+)oK4!gwXxY{lWcVU@2YjK(!jTCpSms;?m+kQ{U?w#im>|zu0(N+^gY`+~F zl=FxOhfQuS%?IrDH-50keArseU*1*{WHkHZHO5lCv$lfE24?<7Z75okeL%NVr?t<= z#eZmC!GOCx<95RwX~n-C7|a}3`+ea8tYVoAyhiyKf=yfoULXee=PzG>^YabgWWjBD zIaQi#vj*a{0#%v={F}}!bdNxq0ub+jA2-^+x_m^inZ@JlMfT@lzj+h7xa9L^HK*>3 z;%_n^?R~TP60j~e9NAGzvLP`uo$-0Jm-yC>%`ki6h(OU7VHWPOW-r*&TPO%$`|m8t zc<@UIjrFogfo-<7nE@sR0}!Ux9W>^TwL2uBJq5cw|8U@;lCkI?-02^>@eFp?;-l;f zk7&kkxfTAH32l71;E21l+0Mp~cg_f5PV+cV9zh|Uwwp041U-LOEj#7DE7JYJ^VGOF zD8HW3J~bn+HpQa&pL)%ZvH&f@%UVoN4>DnyaUI6?#l9=hqeVa_yJzwh4)kxPcC<2w zB}Q2#@pvSqT$Ye@FpTCB0?F9(NK!A0(d4?g#I#GP%22dK z#_c7|4^`STomtN(amvne{G1x1_=DO9hJnK^9gRXas6skY(ck)hs$X?Sdc?l{J{RQ$ zb-UpoEsnvS$(g3RpYG2N{788@3#DVXtQY+xIXbPPjkQ9{AN@dM9;rw2Rgssqex`!- zX(~>AhkFIkx52L)3;*EGfM-9>guPO3EYNHX42L-Rz;}XR!GX*FO#p~MTq89Ck0nl! z{<|~3L(Xpq(rTy?coc9^UtB#V>fiMS4`-dol)h|2Ur}3{QxBwOnJ*OsC1uxp3GQF~ zA!Z7Av$z2`U#6B^8$xiR4d@1HAI-}U0Wpn@qS za8B{jrL?{1ib#9TbLn!D@gZzM?`bX8Ada$2hcH);W1UlyUll%z`ulag z5D`|pf5>~RQ+Ai+Ve_$bHX-K<7Uh|G+U3#rRuuDtXy$Q>F*Op`5G6Qo(3E*)L_is{ zssB!;XUqX6|DcN_!@{g%^Af_W6Y|E=ySS?`yIsE4Gsc*Ps)csjg{u0MS5;e{v4~e1 zi8Z7^C%aG2yx+SgP;hpF`%?m`qeDoRn4R%{vri<`%IBr^iXu5220$8iDVCm@rxT5G zp%$Ti11v37jRFOf>YB)}YGj?!Rbu+OI;KBQ;*_I$@;;K>;UN@dAPxJO5!H&F*V|^^ z^FX@B&vYC@4U*Sv>cTMGqnrVK4MMgZir0ljjsh zcJJXeeo0D6&kQO(wmRvvI6N=Byrrj)qJqP0c%mSrWg@T5PzHqn_?#*mcb zZYkZlqxcNkVVd+`Ea;BJ})WWf2@PM)l`t&uT@t%wrZ${O&xWc;l z)bFtlF|{XrD-+LLI4*#S+Ao|3#V}8l_h**BKj6<_LhXqP3_THB5}8;>?V4W_Ra-}^ z#1yJEP+C;+s!;S+;Vqk|Lod~bSk55*-(lDaKchvAoHI+=LiR#&D&S+#5wx{Rjq4Cs zo+pEf0FNccwKT0>bIc||x_S&9u-V>D@8tBSi0mfBrvUiy~8}?*5-! z{gNtht1wDIc%9#T5a;8d#b0rg`B#N?^9Nkle&eNsP7m5iq{y<@o1T6+%F>ck=`i-7 zV4)#&W^BN-C`dBuO*9JG{66Koq7FfjwSR}HLN+}XSnjW?QYLR3-ue;4Q%Qy$(_`((SDGL#2f za(81P8@&n(@1%`EYdS930ZA|JaZ%fA=bwu|Np2Wb++@c#HiQAe+BK<84!EjHRlO3p z78REd=ZDB-qbEOm2^5H?eML?P_Dwj-@aAaB%rGoh_BKWkwrzauYDHBL|X8KNW#en8mS5i#6Z z^=9_YX~wT@hC@+GJ0=}2%TU70f|)Q`fdP9xy9y1=M@q(pm?Y_LpSoq^Om~7s(*Iss z(zPx&3ayIUZ)1DQ#oNO{rfcXkWd=gxZi~W2Vk0_oH6;g%gN)Lp{H>1FbB>89uG2Al zs)s()Sdw%vZpL&6Jc)qS*elF4VcV5-giClH4n=>=B$m$*902V1s(3Jf_-fmwy-p7r z>|76Pp0=mH`LEqEUS8*uYM~O*f8y2&9*wKhfU}?lSi!RhjhA-J}G zJ+*PS;fDP?%&d-B0f_iGQ)8bX*^N}?PR8{vAd{S?*Va$T0XdhXHqCNB0pa@~=Hi${ z&~_*lV~Ni$D2KfEBMr!c-mChmP=V%r!6r|fUj?qexbHjrmS=VK%uLq#HX9oKqTUr$ z7Akd?F2q$9Iu>yVds7BH(61#I?1(#M@(+I{QEDt7Z>TFvn09)Z8%ZY|DAw2A)61hX z`xM0yJu}l{>=)TO@vBOLCq0i!DU6%O8e!Q(Pp>U}j4o$RszE9ybjt?`r`Izl^NEeJaHw9G)xa3t zPzwPnd!DajFWX{8&-fujO!oKGe&FYl^W7eZj3~r)8J2O*UF|(JYRAZNxmRy#Cr%Es zTyL{Y;2g_p{qmWP-4O(ohBj$P&n#USeQijO7jC*&B7!C@sFv*{DZM4i#RG#+ut8-Fo$uL91)1b`Du$Aki#K1V)$KGM*n0gixOpB}K z8KyB3iF5MId4q%RezmUs>Aak;?E%bzz zAP{bN=O4HFdN)~vYq$4G;a4+%;2 zOGh|K@>Dxle#7$L>c9w`btq%Q&peP;eIRt=V+*;vgJ#O>11Zx3T{gUVzxs-YG!iD0 zldY7}<#WFlS011%>>DgTJIg#&e^x+Uc!thTKwFp6&7{>WBIG-BS#4|L_oCR;%!Fy+ zg*aj++`(U`#wqa%(FIROl94N&d%F59_*=#GWt|}=w$TI5%gQ6 z`>RvWN()M#Hqrxi^mztES)9nx;;!Ik?>ZKX;On&5kv5QD)BWZfyz@dqZ~P(0-b?5x zGe>q<)}$SCUT#Dr z4*KnEOkZ%`!l96HdEGGzY1~f>-}c*>7XE=56VpKbClQ4J{ALybeG$;`Wx;mbGc#T{ zq_0J}dHX+y7We@X^YEQTUBaFcGYCy_zzpI+`XX}sOS?8^MkxOR&e@x1LuXXwf6%x% z%Sfdk5gj^aR$r$3O!dS((U}9hdzmdZ<3A&oeF+k;K%mw}tN?&$Ba(A4hfA=HuEVlS z&&7An(3!t~LEm&mO%bGDn(OSE0+i(m0+gWy(S3T7zD@z>?fo^sW|tq7?mtX+sNlx2 z-Cm!n6*84SfpXx7I(^3n=xsLDzuCT>oP$wf>f0`ThE0d$uq8PQ>=vhGVV8sF7lTA9 zXp@t`Q`F9-Cbp>rF;wRCQXS!?yJNB`r10)YvstYmwzy&o#zA?PL#VpyPs8>VR zFP5tsM`#j9H>XZ1a-6#Gy*&8nu{4`WNY&IgI(<;7X3W8wu0bg&-{E6&c9W{vzL_58 z8BM|jU;j~+Z0?0EOTI$07yk?XxU!grZvl==Nj@>wwhD;{g1@j>msQ@RiCJ8E6Kc!} z715+#Qbf~>kkk+hpdzl!{jD};Rmxl49E+z7WpD z0!FOMc=E^GK}^>f8Yi(cE%p{ZYO8cYiODqUsYJa4Ni-F{b4 z+$owk{Rr9D5ZOYC5EHV?zK`87 zmhaBSU{pW;-#OnopL4wLJNLcsU7maIbD#UHx&l^0MYLf9qEBjPFX%TRE77oe<)0I+ zn6PC|N(MKStXvrKqBdEL$bp92QSfGaL8i>ZrM8+|0!*3{&)f z7MzioexR6z6^3i??+#{!9NXZ`H^8+&{#ac9cK;e>J$7ljilTxw>zQaGW7Mw0Lx_@9RhR~pguS;1m#6$lzr zG`>B+b6~YG1JKTb)u(THu=&wlPdB~uiM#8%ugK*7aCeX1=W7#}Mb5u&+clqcG0(j` zol#e)P3o^+@uH`a8bgZ}I;knD0*fOyyjTa$aT3iKLoz3dBJCk$dr=oDm zZ3}Db7s%M*nd;){!Q;G2fQ6gtX2d5u&Q^Jpv$j5SNPD>N4Lz4VysN>Fk=jaDZtU$( z|8UVV^7fDmDm#HsGZV$_qAuyNB0`8@{UQSeYT2Y)GL`MuLL`BSf2dzLuP5?|Ua{v% zl~Q1qe6YdTRqRl2-rL=I2e7Smp4-2}Y~cO+*R4jz&K7-!@lHSiW5&8ka^$_EP)Q-A zTGGItqBe!jQ{FgkBD{ZcW+};r^Hqxj4gQLCX`4;@TuI2d3Tl?r%2~y7!L(pu`GW1- zXg$mJ4HpIvF!B9MmVWp1yM6K+jwf~-(-72KS2{VSEIK(hauK?Qzmxi`8N4H5*uU^4 z(TX4>{uzfYCrJnhj8Mk>idaY>1_B|Kcu+KvvsV5OgU>>kZ}R+0x&I{Of>DE4U%rGo z+xlIX{sB_{_B}Q>)9_SW(*3Kr_CoVhR-rMNw6_D!s7 zv9N4FHa5_%k4%z`S}S||*A}Jgw1>I{cR&ZY@&dZ2%=8TKW|PY6^cn7?`aWdTHbgvK z&n!423N~SGbe4Y{a0e~84kbU)b*6zWkUc}R({y4m&wv1Q{C$B%HM`=DyD)7D9}|xl zE^UPwM0$TD6tkLT1WH^i3b{SV`RMi)E4=;zFKNP)P$TY+b6RVRH73N1LhP1EABjaF zD=nQhP4^Y-pRo=6^V$R1mH`h?^O%#}2}saMME-4R<#$IorZ!xBR(idkgQ^}7t#uDf zlu^_@H&N`dqg2YY=}$E=;RkN*ZtZ`|vO#%k#EjtCk+KsY`~U~}P75-Uw*1RkoC+J6 zlc?w}M0qtma?{Of@=z#Fa{Dp@e9tuCwB>Sa%fAit0Q1}_yCa^j`e2WGy&J~D7^OFB*iXRJH?2YM9Uy#m|N_NS|`I_ee*;(`t{XEAL4T@_71q@jnh?XX1t1JXlijP z`N8@o-*+=#?S*BiPIx%zH}DKo<*21TG0C)IO!i56;xfJ&;yfqPgRbh$;(QqHsMaaj zM3* zy;wjv)oL;S$0LQ`G;?x2oRt3Mvp!^^lD3=LVsl(`gK}3@XyEzFC$G_LblRo4Cuw*C zSrB=nUDV;84b0T@jlex5vn8$}C6wS2|Pu0Nj zqGb8-%yD|#p3hobejZZVu189q_nm9cj5{PSXPl9par1eACbf{$DAYauXjHnI(N07q zEL<7+LuZ0FtIVfBH=#Txa#-h1m+an#^npy~$evayB*(*6_;ZaSS^iKMebZ<4>8IoR z!6T-p%0Eo=mw(_Y#|~;Eh|)_9Na4-SRGNA*7X?G+zRWfKtIW1R>DPVVL&^yy&vxWc zH1roT^os^P91pRt81+p<(?U(H((I!SODRuM&=_CfPAYr0D1q_eCmbiW&RH$`2ogIT_Z=2Ef67lsAt_}%7@lVdiG_s9e%J*m}g;Kt0Yi;?ugGPFnfahp` zMo6W}$pWq*YwV1ReGZe_M@I$C==C_NX?@l+pypSIkExn)8^3L4(&GzGT#d|OnN8(r zdZ=AtF`QqqGs7xNt<%+1WoM&mOpwoNf- zIvi8&HVt}iY|}_}&PTYZzMp}TnVaClt>6 zCWXG&cG?7r%u7h3?TpS&H!oi-!fS`%`|~~bv>@c?NzZie#~Ar-Ol;Aqe(fcFezShD zNCvzn&D{HqfEQEbDnLc*n6)}OXr7OP4H8mTD?|O6Z2CjT8O|6Q#%QYUun;p-zqjVs z-duFOR}j7LM~UZm@ocXsrR;mxM9t%$N`<;}ZW(F|W6|cU8b;?@%ypW5DE4KtNh3hU zIjZ^6nHC1aAH!%WsWQnrDnr|sRbba@O%}je#G*KVU|oc%2$;4}dFREM8{V-&R%VR3 zJwHUzR2nSRRCjDs#!OSfxZoM3IK5(rq;DRbbdxQtYOts~7AS$9_x!B(C*aW-B}{_^ z!KlPahf^@S8 zwu6hOW=!9n0Pe+^Z;Ic-{3-J4!0B=sL-*tNH_{;n zcB3GIz7+9s>KaEB(w<7|u)(z5c)Tx)Y5jA*eFZ0jIUF`Y;vekNV}LBcaySHbnGb7I z)y*^(j_C?e0f_N#2eGN*J`A)|jUWI5fz>+A{1U%hG(ueIcEr9|x2Cv9eBk(*nkm`C!pV2;GVNu_^q%DH?+%Mp0{<)iK7p`D?LAtNI+2n? z0`2WR7T@H3x&=Kv2e?{83dT{lH5~BV5}LPnzc=WzSiUsgalh2z{5W%{V|H~PTEpJ3 ziK6Z%WVZ4Wl1G3mFwVX!H;Accq7&E4`D^^P*YnSWhYS!*2Xlf_z$BDmoF<68^ke6VZ|tQ#E}j-R0H$qTE-<3Y zEi}rR)6Vp2g1hO$>Yo4>1XtO}l`79V9J%Q1Bz(FUm?(No*#Z^>qXS?;xMY+S#<591 zQT_N@xazfl{wUL!Q$cM;n)Qfw%D0K)kKDY)JbIJkh5<41O~Ey{MYJanoDBNfLKO<% z3av~`_?ZM7IMZkD(8|YcpMXd9J+F+nIV&C)XvIeXV&>2nwwFkhM_5NjBIbN)GgZUu zIo$gV5)K!)i}D3&@d}A)`F(ap1rA%z9yvII;F1gosI$`3Gc^oNN=hY=s_J8-%25Le zOuEMesxFZqDU+(5;2XdFN8zjQY|e$eO@`?>Py)x@Ivbz^e^F4F5m_G8^W5uu90x>u1l#%^Nks ze8swA$uf>@)-C5qAC&&VSAJ}Wwm$ui#x+`wWFbxN{ecHI?mxzJF}`fQUZVwlX$N~Y za)B$XPGf^-#4QZCT&|B%jz_scn!&_6LrjVN3 z!rGDty|^pB#Ih<~tKk?pG3B5-*ZW556o&; zDo;_c(hD8g=Rm+#eJsjE%Cfg6IFi`~xMq|@ngOuNgV4MI6R@dzgZF^I4m=?IJWqD}lhY^1 zvRuK)`<6rqfs~c^3jQ9qO zMW%6zSnIW%OChpU|LSQVba&fbyF4UK`R!jH)zP+acG$Xqn{r(4e)r}ai_v}L{g$PT zLj;Y^O`6;D^24`&jfYq)pg_J{J=KbYdMbHS;(mFlke7fOv4f@TPVm*!f8FWDRcieZ z2g~V@9>v*%@U-_R6Tlt_ku3LPG*)wf@dYLGNUF(uRig{MBd7QHhntTK6dU-)y|i^Q z^UW)EnAY*4V1jvg)XLG+B+0y&sqy@BM!KVwD>nGUnC0kn{Nbs9qbADC`)GAi5ywRf za=B*g5~^*J<;RQ7fA|Lk+kcO7kN)UpSfUztn6F?KW-8ci?E{};*5bAIG4Shgbda?2!YHv58N`uLsO+`m?(kOrDSXwMQtX~Bl&kK_=xA0%-hDMD$!*Q?rciS&5PzB6xs zvu;~+6ZH#oaoziUfS+}qe5uYB@Ft1la}iZ*881L&s|jJ(=(9R>?wIMFA1~e>MGO`a zp&$~c|J85{F?AE|11mt9Fc3s7{rialAdT^meqwu06Yy}1g2Uymo=KDPOw+EdP&i{h5~3-yBdYx4tJsP-p7ufEbAFHM%u|KfcOKG_ zm572T@9}i4)R2;CEeVT^-6@_`XyEu#_eF=rw1jQeEN$_a?XB=e{kZM`+PX}{MI@d> zus3ww?d&7Y5{WVEx(@i8YgJ?l=?^%5uSuV{ptotz2g8AaY|vyuZM58ce&?+0$xD|; z)=BrdU$Onyw`4{)NurXmw=68rifAA)k5}F-Nq|7MEG2g#EQ_XVjt&VM@xPxGi|U(S zpn%bLVFxCTZh26AG96GvS7!4p`gsr;AW|^@!M?NekNAiGU@day6qar8jbq!Z82@$y zo+k^4DkNGfgw!R6m8Ban$hKCnkWz5JV&G-I<#ZgzY8CrO%H>%z{@ucjl<-W=|8=z5 zq)5KE;pO@oYrW4^)vv$@(|rvk2Dq>wB|b5-mgNT3EvHWSN}NhReMN<4LsD0mXGuIR6;`_dvltqXa3(r)f7V zU?M3w-l3+-L5FUDB73{63S0F=Jp*SSl@_LrHAkzqyUGeWSoy|rj+7X^Fm<||`hK@p zLj;>)Xc0^}<^8u287rfvvwr+SrSQmiS`!^@XPIBR+&TM|xeO6XSMWw{dsGj7C~c-cI<7Fi5`iu$)k18=Jhd z0A=jcf6oLX41`{VjS1@-uIVIIULf%0Gr{Duy?if4Er^&KkJyFHCUDs- zic%2&L)U^X?{3})T*n~QxeYP9X5Yzu1;IYJgSc3MS{=q$f9+c-+_pD;DN=Ek7yeU8 z0HdS&6{DkC6C}yR$wOYr!`vYiwR1`|Gw)Z~PuSknf$UdtBgMtj1_8|c8Q;pXqlfd# ztKZ34vnFQRYQLbanfQ|Oa+1G*zlZ0^XUQi@0T-Z58GNm+a&fomGR=E|yMBTGWM(Tn zmtVH^(Wy!e7s9(NU4<&bnoQ{$M;L_!-SK;&>}xpymFtAPG<}U$R9&b1@93O6{|P>82CV2D%Wudm}uA0F~UkoP&u|d3RP@@mRcw*dY|P1c8I( zWpiSg1nPgm>%j#^-@XpQ?{5NpRh;&|H!0h$dKU7QU4`Nq)MS3PA%J~Y|rZmQyvx7q3Pd? zXw|$iUX+_m&sh;gH`92*=>&sX{#byj`Pm+ynLE?RY4SAU_}Sg>q#Xs8vLWS#3hZS! z*`+_iIggb2Fl(l~4!5Z7?yKSpD4ng92u~8iAsJL>sPR|T%;V=us#5+5uemRDaBN1R zVIssK1}QqZp&1%>Ej5s1$c9^`HaiSHr@93B5XCQBG4j$Mkt=56tTbszAYQ^eTjgm5 zaPOi-sD#NNg5Cjr=>{9%(Z@Q-jPBPo9Z(T*lRa++=d#@j|5257H{e#skruYwUPm81 zxO-eS7?o6P2R*}LbnMen;DWGJ00imkPzLT9)M=LcVvr-@vVrE~J0D2=RfhM|CYOJV zjOgau;i%`creHl!^Hh95s#*>38FB`oOKbnZ_Ay83-@ta@{G`7J_%M7-AygPM^sA$< z0byGnnHnS+BGu$HYWBTuc2BRVR){^XN*fQn-pTfbno4`MS|q>2ICsx`4-gQXD-j!n z$PhtIr!U~q@qVVf)g?HC@Ac=By&*1|-;tx_A)3%f`xg82X~=`m~ZXIuwT`}Vin=5KNFuI=Th9YoO%C0z+I%7 z_baUlLi@4z6^Y?xICkN)RS-a!k3oBYO#U4iMkarD%eIMJ2oojQ>~1b|4ijeCi|GWS z1z!&-i92e5ZlM+Gj}|#+?_J8f#kfvdE|XvQepTu`7^NfyOc_M7+qJTi1RAezy*U2h zJTS|9ZLw#dgUBq;nIs2~1f$RFg>1bE`}#0HC(u}%Zzqn;E4nr7S}f>T2KzSdeukN zET>%VFhWy`gZt=?*f~|SG{5Pyf(O^BvD;;~hvgwp1~`eG6d&S-g*%*^qxGKDi9|$q zX$TzStx@u&3FyOne1b$b78+Kct{O4Y`D{1vtOM`J5MEXEK`r?x#M%EjgIA#y+paue zwu;#%xBPg3KTw6gW9O}gn+I9O&RdEI0CZPedsx`xE{nw8BqrbLPQ{??`Sz^1MXmuc z{hpn-ngs*cdB7d{U2L%3+(THiyaRT&JD63zW8>|v8!Rz4vZKfI4M@9PKUqFOHgn|8|o9?Q4ux_+B3fBh7_^&VNq zn3PJ!$d2^*r=eGAj8DH!6_XF8cv^rD60@5zjR;H`%XQr2N$9v|sAu!IDCNOsPqDf? zz$j0CN%{dqi+Pi|I5g~RPpvr14Yx@-XK$N7JPPGk49xmc)x;`It0o9N$$rpEz@$_D zB#OziDXS;tTo0=xu%G`-t(aQU7$lx0gx)JWr+;}o9UdKY6wR#2+1|`QrqU;XibvT< zS0P$C#+i>x6s1J?SxZUCclX>>$&9FLo#JO2kkzS_s7>)x4g1yg&fv4oITO=|VKst& z)9#g1?3G6=JyAZxnlqx>4|)9Vr_yD4 zF&|8z7|M#xWYyR@6{OE9Kmjs zuj?iLkAgxQFH?cgQ^QxEw%Kgn|Nae2VzWgJUm8Fi-%KS=VtRi4E(PXB{C8p_&Secz zS`Iae=ojwsX8h~-H-3yb&{D}Zo}q%jE()-q9!t^3Ek+c%Y*7Za`Kdm|CqGRETW)9T z%W=k0h06PcJN}SO&FZS^6iTpx=UG=%WWwmtXUFyXMmoO_%pQxJG{1an%&SAE0_vNM zcI?Vc%*e=`1l)01hE1Q&I;#~%MpZ_bvea|?7^LVz6AgpjmQ}b~+%S{rV%hbm`s`*! z;ctWJTrbAL<4vQvLFkr9eZjnf$#KD|bM1C}{bLygqAN-wv!Vj?YWNF|hCkPuI_y8j z+kW(Oq@eMg*(^&mZTf6NbZm6^plVj(EceIJ!eKSd$m0EBwVa|SD`7Rb!wOIVWR~Q3 zC}YR7H?$%{u{h|6RW?Hp?3E|@PX!8^`)%{p!*;aJxaZo18%b_wiI(1S}-AUV{p zmL@@Ns;`3#t`uzwmz#La;ZpuQHJ7i=wIC#1tt$`=e{Kx;d_@Mq^0OAMGH{)ze&$n% z_i23Ma^QdxfhN-SbtkTubMvEk9(eqdeDUgkFmqd|4dQ%nZqvfg=7%~9>QdW)x)cve z{>7Ix(bT8DR%6$Oxt#7yh*xwdbS$-VJ+Vj%ge~v-n}uTWPmAM0#FJ37ToH!EW&IAX z1IQSyKLK{m?}sH`k?AlT9p_9Er_Z|xt&|)hl(8nENW?Os2yo>ogpJkeT*igSr>99j z(G%Mnd_qjGf>s$=*SXSS#3I|q#78eU&`!jHV-qbnHc4||`UpZjoBiW<4-*OE^!B84 zQR^p4F}NHS8qgk>=oZtF?j`!oQ|R;i$)T9KxH2~B#{TT+5JaF{!C>QT>Q9H=^5JE@ zvRMl4Gl%FVM_Gd$4TgWAER2##ye0_*zcMkcNHK?H3g36vwzZprRqc4AdDJARya;lRgq z@dU>609xW$c4IVKzfoKaxJcqb>O6NP{KbU7%7#NVwH)_$XS2**h(PlAWigLeO~HQp zgIw9?beoJm_tA?Qb<6~5SwB8R7!3S9N39bl%Opxi(Vd;Ah%m{`e9PG&%h$$#U8|&- z7Atb{h}yS^rpBk^+VdNx#cIShpzNh3t`c!91`ZHPVh}hPJ#}H(&T&p154?NPH#zv; zEZqLeyJ&77e!M``DWI~w;R5CB`*+b;B(m|;8K0y38!!dNds~f)-QhO9GcHllk$Syt zp%Uzq`Z{8Q2AlNi{Gxe)Njpd&g`7Q?*pXqs0GGvG#isr}-L?|Riz#Mxpa%h+W5h9$ zG|Q3^`3A?{z1w0keRyE27_Ya2*)Nv<&yg67hlx?>2g_ceE)Wf#;U3D1(lm@_|2F6Y z>Oi2XjS1(>QQDES528+E6el|n7v~va^P%!)rR$w~5n&No`JT_cC#&g84(SJk-I(Y- z@+0j%*8_&squ3@p8*++YV)}u2>TLx4Ej*LOh=C}2EtNFU{t4pn`TFkN zQ7o`f)ZXXXykauSmb48t&vm7q&YpF;I-^kgKn42i)5RQ*t28lNhIAPy6D{`3*)p9S zX)HeBpK(@sNgK?l_zmPBgG#qN9N1X>Ce8UYkC#>Of>1;IQjcNWV|6z|Q?n-aS<4SN zx;EgHlA2i!btf;-nrFgPi`Wj@2esB}o3_sS>rowHb~@`X9ChxnNS*K`TUF!d%5d_e z5r>3tKE)32zg4UC)H}{{`+4l8swq*__K>NWkb(0@BstpJPiu$EKYo~`kbSDLdq)xM z9Q_271R|;-*eQ;lpFZ$%cmvY-iF+bFjh_B##_?jHOvlJ^M#pxxyzA!mPNcN>%}h_z zBa)rWz|u~<7X&+ym9%&w7k*AO4Cn4BM~Fq7&!ighWX4FRHX%rM`eb)K@<(UmSNYOR zZ+QruqdX?#veEJM{HZt&Dkc0{nIE&k>Pg}W1DOWV7O|LU)1;E5mgrr~_O#XsvkZ+B zYF{!~Ao)L_FM!6w)=_Q>W9FpPo`Sg889Xd7|hg<;EWTmT0fJxLfZ zzz*WZMehK$)4BeQ^zV(?9|eME`!KLRe2AxLDiaWv<1yf2esrY?TjbNZez~h~Is6jP5_3@0ox3`JnsQaCYea9ItH8+0t4g22 z@`kueM@)?V_mAB8)(%y0wP|qg@YPj9JdJ>c%!XJFct%++nY&3`_5{7kyjCGb}K%=a{mUZvbbv|#d=1-e(s&6fPC>Ft+-FwseVh!Mm3=wmf zh&#Y51SaB6CzSIvZsp*-MnND|U@KYjr@n77cL4LcDmUEdi`94ic2CyefFNtOGsEm9 zK((nj?nC1jZ19i)RI|q93^4r;7d6!@*PpO=37(sV8hwQGiRvXq zIb?sMD4tIHHWDYEB{)mlUuAuH+=f>1m`9%;1N`IdJ0l(N^5PlI)Wf<7R`$tiKV%gv zLo`o_r>gcpm$dH5%oVP$Wry2w3doMbLWSex<@6JjIB8|A#-yEgAtn_W5L~6LqD94% zUSSC*DOD#bZViGL^!)yn8LVbnd=;BhI4W9E{66EhcDP(P**{g!(} ztf$QObn%mJdT`D7u~d4L3(i-e6YwR3IW8~Q8WRAwctv1R|9YgCPZC0*nENWH-Sv$u z+b>@j%r5leqCdZNABsnq{cVP37}l-NN`4lJt6ff-Vhk$EP!RP({vL@_M@{cky-z<{ zocsdEJy=nz`_F3x)VdPz{x5I}EHG3n#_#`0@BArOj(m5Z@c3Fx_b3?;nH3G?x8Q43 zrk9bIGk1;ctiR&J!LD8NGG+A8egX0H9-6o9w#@+(j1Mg~GCM$Wj>a$Jo5K+^y?5UoTaE;+M|E$I%%{f;cW++J0W)$s{+ML{#Guwu5!# zL$?!WKF$rRTpp-aV=fD>6LX2IwzpvF7aAIDjjKs?;zT1-qh?{1LQiOCCX3B2Z zxRZTrV65*>oF3TH=-U-iGxo9Ve-LjvBp`BeDPGP&vM+^S&T_Y6xTL`qy+DE@R(FhA zHUZa6OJQ9eDPa0Uq+JAl{cbD7KL;CFfXD!FOhiRkB>1oI!>ZIKRN6`{`}jq>Oy zX_s@LiL(DSIwkss1ZG_gIt3*XVJKpsX}4KqU6k5nFD^C=IlmFN#}KvTFU2Ab#&@2> z+V@gP#!{K<)dlQPQp32e140mFy3~5W-}KZneQ9>{@aA7+(yTR4N_JgH*cJ@GpHHhV zZAR6yudCUk;^yGiwk^_>`q$jnwIoLA42oQ=Wm;D;Ay$|zI?i>o^f72z&Ig4Occ^0i z`+*PAm#>dYwDf2rbuEy_my0qEi6(W$3I5Eo$YyuCjC54CowZB(!UK00YGV%yY)>jv z$zp^(df{L}TN5Q?8`-B6`8>0gqnd-CQK%A#RlUL{}xA@rptT6rnr^jEXxiTk4TI`@V ztm5BWf(!RNE#Hjn>MRg}`Wgx;rGI-Lx4wY+dDVVRwSwO&}7ASNFQIXa@5RM+pO zaXIcMDzlDi!JQ?39LxqRiADtb=7`Iis@1F$)Q+4v*F7Gyj#s{@!M6T5!hrgMy)vd`H zx7(fJnQkSxcwZK^7@;Hhi&w41nu9m+^MI4{FP}7SzCKw=A(6KZ!&8p?0>;x`KOT=# zOPD-kl4Wy)b3|jGZIRDN@^!Du;(AnVTU3&1xycx7Vxg6G3@{0oIl@!wU*9tz8MKeu zC0MP{qZi>4%lD3i*z$k8TYh@D-ix-n`VP z<33#j9$8Tqf-QOZ1p6~JL88R9lQyLJ%zthS=*7ywSw@24pb4(4TzwD_?D{ff-37`G zsqQY4C!EPIJI`$w{s_;0qx9uEdD9FLu3$f%lKzbG#i5$s>(VduQ2|RR{=YOZf3sph zQhZld(-9J2Su+{|e4Nntj}8N0$~?M$3Q_mme0r{4^=Y}Tx2sOY#af>7+h^e;X`BNM zX%lK=oNdfDVk~9E^tc&v^tsVjLRGMrDc zrzzpoV?$A-UihSj7c~d_h@@<+Skfrdlx;lu&hi{ zTKbuvoat7IQ1XIOpn0ApD_GxC*BC2EHRiktsxH7Ikrp2#ZIO%~G#B$4J? zNiP!E0o(Vrj1<5QZ#JK&-+ZrGnz7A=?8f?8ajHG?5d+ol=;z^zd3fW}kC$I46#wj% zxFgrt_Ri2+HcW$JDR*Sw65%I?!$cs*bIMjQ&|bxq#k2}LOGps8n0L6pzoFcSrY!Cw zP@;Y1VXU9cXJ28cjjSSKU)VM$Wh5nq6>p`zc;4*hLv^hqZa)<^_jq?*Q$TM`kvp>8 zC}LNEr%F{u5}C$c<9te((Akmfyb~ocn2=k}2m&QRXcuTZ!^g6Rucb;V9Zs_{Og4(- z-@=&%*4NSFP)80kSK_oWt@#I7Y#UXpOPRU8gIW8pBp#|GL4s#rizJyxF>E&(clr$6 z1fsesExqFCCQ*}OS!cicsP#D9nKO)zHj!Y<@HXI<9T%u{aFo%@u(G#=rXJpusjqw% z9POrb!uvekK?E+#xVjJJF-1Lx8TuupOneZmy>o6B{gFqf0)nffIyiMcp!5fU31A)& zfHJoz6}8qB(w99!@b0LLt-AF7b5+HSm;`P-Id%4C#eK`nz^4Ox*LGJpx{71yu<9O1 zWXj9&%sPg3kZExq^UQ&RntF}m(Q}wP;p9Mo%QV!4@CaGS{&;OP4aud6t8?`Wbfu+< zD|a;ulthVZStQtokP_)&UaV@75SZBcjr%Hr;e`~X!xr+HT*$$A2w+R=C|B&+pMmQ= z?)p8~f|ySft&UZ@H^r;n`z&ESk&>XU$LN-<$dbm?vbugOoe*onA+G%e}Nz z#mzD0>3-oHzk5{gOyhX`VYtSSfbk|5*oTH*;0#<`k%MA~P@&P#{z~@BLX_XI_Rx_q zxOcKdURd2&yna;1DWlpRIUL+_{_#HO7GQTTEhy$XLGz*J*l{|kF&pmf!Y zw5-dpO7$pLOzoc@NI4ma`)dB`JXeYjRyF9of{x>F&Ls22;P(}x-}qw*i8Z;9X;sw6 z@)FmE+%U~qVU@2QxnT-jk>9oI0~`6KC1yQ2>sikq(zT@sQeJG0+(2vq zsG+MUvbDnlJVe#Xn#!0+RzwvBjJrr=*YbMw zM)fE1b;$$_RCy+MPt?h#vPaEMhDCNT?+`4|wti;ttml%$HQO_2`qmo7Tj3YVGeH!B zpUU*q`_8!H`kABl@}Q03*alM}rB}`U=#7IES39#*gV5#)W&?!y{T$Y% zbq%#hYdXG5c=!-*%|RB}ohW-nk?@MhflvhQzHBR6Mx`zcIN{6xJ^@J_+t#oi@$FdQ z*tRCj`MYBqWL20Gs2UMsZMQUoSleV&>XaoPA9`|NftE2AmWtxvNn$ zOPJ{ly>Ni27G~BV56epY@2CRX z1Y)iV=H$QWJiXh!E=h&jZJW&22U118!$Ov_1T32|->i7}#}u=EVWwg7g1==Ll*GbVN|pQ%z=9Ew+gGOi3xaHjK4RsW zxhL(HZqrq$`qWraBE_bQ_VABuu1^IobysCR&pIC%eo6I>#mk*LY>Y0gn~66!Z9AW9 zpYv}vGvkaE)vbX$4_#uheUT%fj776t8A~n~L;)2-+$!Uvl4>jLck{rBW~}O&aC}u| zX5p7krK|(o)$ajc)ruJc<&vwq>;lTK4xn@IOFl*R_|g5 zJKwTWHp$6ue)q9Ls+tf*?cRt)HJ}k4!1cklwE)$wT2nVr+AONVZ1ABDYaT^h^9fgjHK+MEL zXRA!6l=@UhQ)8TFN+joSJzde0-zp~xmb_ZF1!Knse_0heUtZ$h%vvH^kI(|*iA!=* zSSwd@rA?if@Fdk3TpDTMkl2EEHhg?ghTDP(rD5-uZx;Q;{8${0J6@aE41e(O5_Ev& z2Q1ry7nMnj+i)-bJXe;F-yg;XS1@UC5L!cNKY@udQb2}!>35LpH*=?8oO{e+6`?nqJh% zm$@iJ5mMwbAJSOVs10jW5zt65s<@}GhoR|1K49#VT!UJt+6FsD^gLOmvutK`X#=de z*~i_d^o%}w7;<{*bxy*3TXkRx9bbJ8s_k?1u#TehqDlI43q#S<+Saypv=@dPLJMcV z1InCM1Z7TBKPG{Oqc?_9uTvR=Jot9j`+Mlc^j%v^QfwZ@Ud`y*a@F&DoXhCedug;% zU!;W#Jny4;b=$WDPs0X-=Fq23AF^pCa~4)#f=D0`_H}!4^(6K|zAObn_4G0_aLfiXisYneC)%N4Tg>seq}4{S(P47(CJ*bF&zLEq zE4dntbgdjb`ZBep##0SZH!FY?8kyxoI)#hRO~Yuf#qc1$WQ8S5C&Him3*NSCFE<<2 z2$6ptg|L~@PA-p%3XT-bgnEzmXeoX?j<&L;^ptm3Row1A`b)=Rk4)4|I#a!JWY2hb zuGDqij3eI9XUWD>FHephhhH3mz*Vh6$nII9k;7PAZaU|tI3zLaQ?%hBE4ba8uaHq0OVVC00kv3 zQnlW49PqRcy#0t%wcf|yy58Aw;=1PkXTZu>{!fh;Y1C}Xd1_8qLbZ~66Z!(H{-)*F0$+xA|Y z*}w{85xSRh=fMN=BeD`hk{4gsF>a19${(>|vYFt?ODwVEJk9rdBQkMIrwj6`Rho@9u{Fg?KIzjlJR~|kvwfB> z)GAvs4n0s+n~pRQ2iZ^~1Cc6F`ICa(u_;dA9!U6247Ewt=&OiSM9V+>XHU~U?}NX9F;82RYP>2@+;{dH z&V5ym&Y<94b1R^^lL-_WUH4*k>S2D*w-#w9aT`(dMX*yJhNmI;eTLn>=60rWpHo1` zPegN6A+ys3;1U^(1KW!Ng1oYy_?LwzD7zX}<A{Y!EVWadH+s;w5ECT>7n^u8*dWf?;Sa}j4cz+e3>0QgbLWpQm87FO z>j`sg{_cZ!Py8De)#_%-GCJ`8X%j@OkZ}8OYT)N5>j(;@tKAT>8#IY?$4cU`lnu!U*XAYS==zCDaqxqAn8CyZj3H?L*Nrp#F-m<(h zj>zD5m2BSTW@Gy_IO{Iw4P}KdMSI5rDJ7rXdm73@Gc(idKX(qekIL}0=$Nk&;^e}q z=s72q>8Ix5c1utJu26)fMS5J`u;=YZ0w(P3zaW-Kxy)q`HVP>ws8dob|gtAIXKK&$V65bdNoMMiobA#M?X6y zB++WlRoc+gRCCNd<_;qr=jepHbUyX<;d*frevtmSk7N?5j!;YwXK+ZnT@NzQFTxvP?uktp#u%V55$ z-{TjcokJi%b^-$A;CIL@ck_d^F9PWgzTt~FzgRsw$6ygQ8T)V8WCd&MwPBMLIXbHq z#u8aui-kR^Jeu}BEX}O_>iq)&VwTlcEM+ObT|Hdj^xem--QSIq)p31O&VvW+Q8JG( zp1apylw;jYhGEhT=)A(j<+;ljzjOIk+uLkn3~>rmEHf3p%qCR(2pnya!O_M~l;G5U zR)nosNSmrUN)Nc4VupDbw&wLC^zsVAtkBc_?0z1ud8Ms)P^Zrbey)U;>CsJU`f~bA zg7|ycvXd~R{f{1~u2-g*tmKOsx9F5F-ZDu)KaSoW)y{6{rcL^peyY~gM>zbjXg@h( zv`0VHBChV3{ULMPBt(|l0BwLO`eW@Vyg^lQoX$Tu4fSsBpRf^0;BiW@@IZUbG}q^m zq+|(;u)US9yVKsE(&IJ3%X6wE{7mYj!}bDpoMkJ^-odiB7EQ6Gj?!x9Cd3>e(@<&2 z+p+@t$7uyLdZChohDHlh6#Jw=z8Hg$B0|=TK}akjY~^dhAmDgF?6tsbJ@@PkC53+M zs|dLQVrB;^rrn?i9b|k_RPB&GO8~P}&_;q6u%_nYsw0U6S4-{T+XLc!VpLTy#Jskj zLd?C5#_rpq?(yw+LU8e2x}i+HA?di|Zf4Q+i7gHrn{tG=D&E@CBKgqf^zqF#?v(u# zxxN+@c}ArzMmy^X3?k6hGbCbY?EYcM7Mr0f;6zE~;ZW=Tvna_DvzQQ7II6dq`Nx-G z3dQ_}9>rod-Eg&*(mqRMi>#q+@=m5K&XAg}oex`mM1{0^wd!He8>$_m@{>cdFlmv% z;hK*}%M#O=l7y-BuCq8!JQvPDNmuf?&7E|_cZ#NO9FB~~Zi?Oa2%F=>b5 zcqMgEa9s0VnUhaLUml%3kpC5^dBr@fK)UdCGCr(%-SDgN1GfK0BwYF(TwodzU}SVp zQQFLq+o0Rq?OnLHT)ws6b6Y==h?Dww_ij8=0%B#}ZmyLU$2?v=;cU&d{0N;iNM^rP z7WkyI{9QKtrUs)yz7(O$BmGqlG=@>Affioa$0tEqvO_bI6Yr`6MGts(di^MRG5uKE z&{wj^fr$^gDX%)bzwd-U2r%VpVlTd8W#H2yj;Fko5R;KE+^WLQn7 z90?sZ$q1P65e|$K4l(fQv~e;9muy16nrRJx zR5bKxe?6?or+8{uZPMxHm}6WITG1i~saFEfw6hc6-S?4O*d<=>{yESD?!a6W<813X zD8c!}J10Y}wDtE0rD5-8dW(Ky@~vC44oQTh`MlJ|fp{h03jEKLhx7q+bu)SXq`M;D z{4dbNl9`O_7N$K**U2IXu8L8oiF{%J!qFezoOR!2Rvkj40NIW5xk%73|4VbdMao|g zcEd%|=6d2mC9(Uis@aQA7bJII$lAzaKLXdXPss+l8gToHZ7*!z*}dX6U7gewPQrGXsAl2Z?kD~msJR2{9_t#$7^xOmtgh3 z;)0IZ=A#A;mG?5oI@u3*B&Rv**=RAubhtDQSO3aZNtskvYyHB8&vk2XwudMGm4p*&=unW=D197Z4_$G>A zrk!Uw;;h^U-b5E&nB=3GfraAHsN7Bdy+nm)OI9Eg_xNfcj2a+gpZR-Wo5@KXBe3$I{8?tHt z;8U?*A3s&WH56#HEsNOu25WkPe~-I$H9HW8N_crHCEc6x1y4=yRbW$`mX9Cil~mr= z)Q{f`-zu4FphRHr_UZ8U96jqp8J~sXDOH}o34L(lG@oyN>B-uS8&c0G*zEprjOyC9 zUdzV2n5cMiLwc@bbtQ89b=;3*d@XmLaF91^hWO_!lL!CYz_AE&;0GXHm#u>{x$mk! z2|t{fR=vD^xK%1&E-)0}l08hGw{Tx`6tWZx=}@K0HK{V46quso2^WRx#znQ8P5i3! zRM}20ti&&Lc&?zTGi_)HySz~23PDsbaam!j94aGn1BlcP#ZZ;)&oB`oTrDZ zQ_puxJ8$_~+q17pd&_>0r>fiU@O+Y|pulk0PP}mRh={AV+9NlRPOVyDA!I+$Pk+Z$ zlnl}wH_ok^x#=O}CtAeK^_P~yFsGA$8C18gm}IuHY-sgUaiya+zFq&B#vyIFvPK$b zMaz}7&^QV; z_EPQg$8)0j-qi!&eoisswpQ5qfF8F2u$3A7dcZnbF86`;%h-(?&%{opS=`7tx;enO zyQp*U-}LV>-~eT*q48$#3%Tjj8rM&4)EKY03j?vW?`)~5FKA#qOQ%pLmMAHfA2NIH z3oGrRrq*9A+H*Z!Dyj4Wj_+@4rdj+S^1eJC%I=MOdRkOZB^AnADoU2@Yqa4}A+ki4 zk|jH3-%E>3QVB&v50&g&c4JBQEo3){?2PO?@0kT-X7tqfy??x)cRn9;-|o5ZbDwja zbFOopYx!P3)1skn;?JF)k}>*PghJn`cDD&v_m@V`%-K#H-qM@E{9@ANy~)umrURCC zEy{b-ZCXoP8J>;?n`#d&%$ckE*r}EkaQY60hA_EkezS6Bn6w@p)=^XRPMbq;e&~D` z9d3|(tYloS+AK~TmY8VVe{s%u^!7L(RYb{z(`v6?2(l2rwrjxhZer<~-_yzB4?oh`(8_zk@O!l#<f17xun6rOABKty5KO3NnHu#Epk$)xo*>U`fjD~e@=HJxpI$`gr zKulTLyUT@{&#GF1x_f9z-HmE_S<1vvYH)MI%)mf@ZaYk9{X{+a2Em~cVO6I1F zo(FLR%eycYl^?G_h>WO~00qmiO zSNQkxoZ2e$?(5h(XD419^)IN&(Br)3UpJt8E?P!-vaGM!YvlbM@#04i0S&|3QQ<{- z5q929DTcS53Gm<|2!s4%w>P853F_--5OJ>^(q(Q`sd&Q$R~=1)%#A4#Pg%#SfK}H0 zyODr3V{~%r`ah)8h=;e=P+wv)dxUz1Yd+xOzcGtma++hx?CQMKMf;fJ7&CIWv z{lMgOYzpNAb>=IGqwhKH-@Bgl-qwyHD0FIju-Iv8j_n*8R|^&1Yld$duGqgjeo|ph zY^wWB?#X}zVe?n3k!K)N)Nl08Ey#JQIrA~~P0ODEdufG0kfG$M+Br0(Toc{~c5(vi zbIl!KeI9aoagzHzUj;<{})`4t)fjx<$dr+3qc; z?}>5`0qYshwdo~|@a*Ru3j_~?Y%OZQlt zT9w4x(3K_1ruW#Cv?x!rQ|dMxw;!~Yr<52T4T&P>dJUJ+e^H)3<=IW$yJxm1v+X8}kZ$(qUBE`?U|0MItUh^n_u z;ad>A&5*7@BIHi{e3P{l{-#>h5)JiTEX8Wh5R6(|Hi9-haM zLbChvl~rDZj4(UEq{F#)8ZEmoV5zirdPgEEyCur5qanZGte|vKh8(~sis20_;iYS=hg+Atlqd@8~|N4wOyv}#jUp~rZPC|NmLEXZ&=$}9-ln;y2h3}` zTvgWPoAKdyJCoJO>0x-XRk5Z_3Y8MtNg9BJ@bGwYsavC%l@PV{w*$W zTs{G41afJwTv;Qn1}WVLie4I4Yiqkn=Nzb|YbS^d*_7jLJ8*wX&lbaAmu)IHoKEgF zp~O=t5|dTYBJNFG5tpV4)EM`(`Z2=nG~nL#ZU+g?h}a6ON7{+AnGBadFAs68IO46^ z!Fcr*oAFJ9kWys1>DS_&^_w?QD?AXDW5|_yOvPkPm2}7h=&6GDC*<1O@E8h4#$E~u=WkE1mY^Lt)T9O}&`rs9 zd0#k^%hoPCs$O)Mc~+}qLdRuv0NB7jI1SAg2&+ldG_@doy5lA|OyOeD)YG|4Swb0w zoSY*OW-`vR?I1x7`QdnH`UXRf0k(J_;XG-zx;W>--l+zFtCHN8Vs|s+%C2xzzWsh) zA9`y>H7C!Q3DUj!GCpqFK>zZ1co4|5d!1vxgn<5Cs3^WzrPIX%`EST@&T>Q4JsUEwFhd|1{b;9iPmYGW{;w)mF-hoI+CpVrEI1FWY%D5 z)pl@pS=3}^CJ73_E9u{)`;K((5 z!l#a5+2vH7_?UGcY``MvllQ6e3kw0?CJ|{v`cdyQgAy-5Tq$34`NHi@ALkgGHcX2o ze|fvK3ji%fC8bCk+ty* z9*F~vIuqn)!y5kPDLWEpS$+JQ(wUP@RiVSr9U+Wo^2p3@9J=U3r53Q;4EUS-&>s2* zJaw`hKvq1PM-E+J879grR@6jG^^9l}j+o|5tR3y9s4S%wq3{&FI10jAYU;x zml3>j@CGW8{q#DgBzPYYQ#h&?q=+2gF>HO--n)>x#%ix*LMH=metU007S-AhVFKQW zL$aY-f%CyjCeouvH-03QRqJ*w>>X=U>}NbKavhJWwrArMg*nAhbYOq`ujx;WtKxMr zDCrMZ0T8nikwkI+21M*c)VspeXZsFu**(mDYNK1=d86n(_oiSmm{y_OOYW4vkI1l6 zbA8-)B!?^W*7JgR*2yiDAlv!Eo&8{ofyEvhm1xS^eQ((dTEW9kdx#`Fa6WrUSJP>pW$hdCr~*uBXW;vwI$#n7mT zDwfQRJ8+xlw#2MugXfCpwW|tS$ERdj z{eKRXR$EvJpDRX{jq@R9UuU$%xdGIKFx@RF3|yVkcY_=Pl0;?Tw~@z3WO znv^R;8uc&UbVlu1aVUd+0DS!!HzhWmQ6;UbrwH`0OLYTB(s~M%h%0uT=KSh%?taRX zWL~t+hyE9k+RLvdW~5y4db~(`O+)%=vG;&gd2}(a`u7cxU!v)dG%N_0zW>3n088Jc zO(%D3Jaakl7}rJt$(svL6eLdadLz0R^Du0Im@tYT-Uu+rfw%AK&(|E0UE+K(%@o5w z!c*^jt9Zg)hjHm*Tn6yD#Lb+f{O{i;v%5bx>%92pLuG-&?`g{P%apERF+Xbh1%w4D zg-@~E%y_-;{y^HX`zRHYzzTStfM(3G3J-V0MB{M~meAVX0>TnHIvQ@rWx;2YA3F~j zgtOH2$Tizj+q4GpML0UWHscr_WEIbt%PdwA53Zv>zpsPY!!){GWgkp8u-j0(eX?a!;`I0yG7D~tQ(+dqB zNAMNTX4WAcSnDQE`A9)jZZXfA@H}QI(Tg9=dOdYmcr`&G#(%NkT|v2eVKq-HzhG`# z{H5qc%E%!ceBOoJjSqE8B6cjvDvk36#^a)HezbI z&6aJ;r%NYmPU!}4AA4404 z1~kZRZ$d5L{;is@@k^8Z z<@O&OFj^i|)m6^J{f8n=-RN~`lXITNzsO=9oJAV8CI`^YW+K>7Ol;wBm|T_GxU{xQ z153j+g5~l29!#5;zo)u0md}??{O(e(iII=Jhm@WsB7%@M>~OtN@dXBK{r+q*UuyW0 zb%Kb%uyhN-9Kfy2+Qh*t@qe?Um_U9+18uflwExPuqwTM40O`xeLPqcY0E#u9ChNdv z)<9RwmA({UX(o&?OKC`l$6svdq#+lXfuD7jE#N zFqh$G>WN3jpJqQFdCglE{FTj8=`vVp#U6>BXDn3txlQrYi}x4)2GLIe(q{@U+&}w# z$c?9)0fax5snWe#Z52z-alX03C8DMjg`(M=PC<)7?&^26!6*f?Jx|2X$xsc)I`acm z+J~a;&r(J%lO9@X-Zfk zOtJC+X3LxH!eUaG)VH(2ASvmPNLhaKt8bHoX+u(ZY5+--3o@5`y&;V3A{{4LNo`P0 zyQB+dC@g=c?3}}hO3PQA2^@mgKgItqDI|#oK%g2z;uHrghfq*hCJgF?1lfZ~iR+g= zfEUH(O(@aBJVLOLY~!u$O;ZAUw>^I1VEOlJY=64$>YByTikNtY1Rhc8yjY&*t*A?D zdVN*1P{EPQ6L;wsT;Z8Gs?<7p$6B0YwUmXe&Tmp4Z0eT6j;%pB51D%Xhku})2QM*u zzcamX7?sluC8N`}hRi_j{XI#k_E^LR6*!4v9pw*>P0Y5H3q88QuW!|Ml6r{_*yFz^RdTeT)N+pQm}>C56*<8aKU-a>TwRnYk;GlW zsUYS#Ui-bLNM0T}D1*Yqm#>Tv2Dtd5Z{DfMm6W^P{(3iG?&etlmPF_0)aczaMHID00kc}2;kJf?XIXtqo#b99Zv6qQv z*I4&>Uu&eShcm6U{YN*1B;kXg#C6UObWMmV6xOr0f>M7kMgbp6h;kM9hYUTo$CnPc z>;ijjNwK@OEA%=VLO|`MilC3A3^_FK2s;SUA=>y?e_>`#i8Zje!g;!=qNp{R%o4>q z{{DAN?3+mCdzJ69>h@$DY@6gShqVLz!XujxnOYtK*kUKUVc$;%s5<@J30SW=gDu|L z3W1cnbxCf^iclJ%rI0W4vOdf|%2ozEu^KB)v9N}%;d;}fZ0(IB>CdGuJr&QZDY6)y zhc-d;Wam2*RKJCXw7||ZOj88Jv={#Rr=tyF%hMGnwjZs5`ubR*}KIxsaqN(O>`BL{XbQHLD27R#WQYc-7}%bn3&5 z=2BpQ`oY8tnedFG=C7g6_wRi}+V3HUKL5ZYnsZg)SS=)$@>UA;_qC5oMZqnx; z;2~}_kh{Q{#5>lUamV$)cD_B}_U7@$3HhV%@DM8T83`Z8nezz7ne!Y1C*J$+vsoV9GAAZ@2L&F~@FwpDaw%Z)Dw!-Ufl%kJR$q-3=Y|@~ zfD2lb<0tC4=lTY)?&qJR94IljW>puDfSm6gc?p1zlt*_|{xI(Dn-7@Qv*{mg5^jtN zx1SCcnWLa(Z2#^TV*ffqH`CGHF9^{&-vm;8WqK;#+5LR54y5?fX=O6{cATRs?P-}q zOnyj5umD@1t+|V%I-M_K#9Vy`05P^tcO$JHa z79wS=3;v3eFbPD(wG&q2W=fEsobQWOivffEQogzhtvu4lCwuF2vSl=|B*bO{n@< z_e=-xB1&u0_nzq5g9Sj7&jX#4xuGcfvH0~H3&zzK^dXENen*cJ4UgO#{B5K}siZPcr)alX6&d;1Ng+K~Hx&=hG-!_Ot-X&7b!vR!5Owl&FTc1~KV8tGyWUN4CfZAfjo$gpdl(?Vn|eKBKfx!N(Emy9XeBi5h%n+B>toqT)}>Ad$F|mJ>&B0ZjpF6L3ytE| z-|JjnmOCYgO(wuVoK{m9=FT?R_Y;N@rZMg2Et)2CCNb@?Sh-_u#FzEBqGkWen1QqM zW1I0Ck_drDfut#jx68&i1fZ+)8@I#O)ZedbF(x;!Pz z5-(Mr?+BM`Q6EoMnIGs5&zhz5R0ApB`Js`%tO4hf5_>`bnqlUo_Ro=bJue4U2U-~4 z>_db{rnvE!(toK;R9=?t75(Utbie0yv#e6m^cIK+^Bs$fl3B&oVcJej>Wd$|*qPX3&C0LJ0Q1i1lZ z_G@|19YGYd`GHiF&M-?d4^=2JH-WaLw=Ey(iFh0s%|X5vX7tH$1Ba}-J87&1mQiS0 zt_?iC4snF|7HO$|r0_ye;?YDC6k5{rsCugz*IgHOYMjea=ybPKq^^>Gd-+^}lkOqJ zg~kV#+XfGg?%MP7sqYTR4_r{jI%= zZv{qqWQpv(HJ&~l;oj3pmJ1SmUF-%voh~QeU|bNQY*4=XWGK zb(@#{fS3FH?Up#Lpn3;Nd@Aw8E>U&)_=`)~d27web+B84#doCeTX?#j-Up0~PG z{ekj+5Ne7Mc+Fcs#n0WOic6j`?W7p>Hj5Jx@6{U;p*U_MMps*D>iNO#dq8i@t-!pF zwD3B+l=9Be07naN&X~jEP{e?+nr9tF!@H-E&m|`g$49*^E8&f~Ih$iSG4WC0*cK~M zdqI&tpIq&$<@VkZGvm=(8GT-}ZYA{%9QG1I93|Q#JnWJo+JZgfTRMaC%u`x;7igfJ zp}bTEj!%b<$M|Y#XJ%X&Rcy11XZ`sGX|~T+cJjn>52a8JO17xNO-0K2HIwO$jE2eI z-*HJ3o*adH-Vtw&K;4((*XWs%o;Lc}&0Vi$+M#Hv*B}lvd^VDRpBW;TP*;RcT&?mzqb5q$HpY>cfvOhz4drt zya{a%td>4qSS}F;?Y?W)f=UO_K^@u}5p%3Atu}u_Ni}^uInr}}3vLi4|#asYU^%Mh~Z-odT1pFcaDbltVX^>(BMGe?7z z&ofhE=wz!ja1e;{0bCti=_x!Zmtgn(|Bw!D0dj=*l2heX9(tMabE8UZ!l#q*?=L9N)$77VXm=-7N?y$!Ld9kr_>h`s zuteSLG%BP&wBsTG->KhGoH>~RZ|nlmal3X3B-_dw4#tB8rCuI_KU zFF&U)8t?EjYgwEUX6g)4sbHxzw4R)tEN<85ZONA$&C?0w>`tATVheiHSzRd_AswkjL$^;Uc|h4s+w2X)DPzCnM!2=r9_qT{ z;N)w{a74M+r}~ED>9F7)#RQ3D5tpz@q5SH}u>3HwFUc=MtL3=f1b&$1y_&8-UMm^! zw_9SR9wt`aby16Et40*rS*eE4r+W(PtQIdfP8yA8nh8)%IHgyTwaJ|tvqzlkKt?`_ zUPS)8uoFK(r39sW_%($2pUj=*Ay2r@{Gpm>~34U2sKrLVpzM>*$n!PXQ_}c z_c@CTj%EQwq;z5P6pUUki3s{XEunHd=}d(3=f)OUX8{10WXGZ{P*EjZakxQb2w0&} zpE`+CC0hCv$>AWo#;YLbrxSByE!E_S?k{6BGgR|6;dC+#a>YS$v;2)^ekH8eI;?#A z9Y2*9`LQ-lW=WcKf9H-j2#2BO((zF!E3H6aX`l>Ln^#@3zsp!{#|&cOx-uPmRcJRH z>DKa5Aj920hj%F4qAfxq$b+|3L`cBQ-70(;?IlnNugpiAW;R4oXm|<&$Kkck@E$|X>8L4c_i8<7Os1Y)F zYI_cBp8`!~X0D(!rfH}vVit`hs0V}0LmU#Y8O^vujNw(vLf?Guew z(B#O>2M)ru20zB$9T0+zD@)4i!@1B+&xU({V3Z5!Es#&*o);|6Zw8Jz75;aIx&cyB zMFC{-77hG^!IuEt>iRSj8t3;rA=z5i$g8MFuRqHg=e6GV&k6;>8A%g}V2G@Dc%Z5T zG~`QxaRsusTuo1pweF41sU+j6RF1<`nVyKMdKc!Wm2YBNZ^FzxZm9UsU&Y0dL>Gb$ zO%5TR#h)`4z)&xv;*w7Pq}gTo?>56etuylHbm?@u5?QHG?f!_;RImR09{ldTP#NcN zMmwo5K1S!?G+68B*Vetll%q8q4*-}<&dJkdd+lj5X}o^ys7b=u&h7C>^M-x*Wo+Kg zhluYwkTxkj!!^!cCDqdgKlc|y(~J9#^@0Kl2is1yeV=p-$>KO$LXW)tRi4F&UY~-q zuV3wiw*8oRT6IWrkh3+Df^*=T(hg~T#V0M~Hm1SzB59mn-7*V?xBL5@oYO0Yz%7suNf{N&Vwii02?*>>*EhIX?{)cU<*R@O;<<>fjKVF^49 zEf~&vef<5yiiouDcV4mcIqq`G9(S+G%!;0bH)%FbnmRDLcD-}F67({Ty3*7{?9EGO zZv5dFk&OaAS@pTPnR(U!;Gb+(G$wDG?^=*1;2zQjAihBSznGZ7FJd)J=v%IbxB~H8 zw4{3jSJI`a#cT3v95VEe#3pJR`j=k_#H6?9m#aOV@f=fm+(i*{WwjWC^$pvC_a*S!xIT-PI?Z37`w@HWQKzW2=~Hrac8v~g!HY40zOYA~Z|MT_JqKkg z>0iQ4m4G73IqQlQG`NqGTFGj-vJHf?Fjl{M4={w@iE24M?rj$>yK=GH8d24tW!5`j z)Qh3kqS(pXp-2uoT_ePU!vzl(LOu;SjAzQx7|n_qJaH}Y^N81=))iHw>MU;!9-Gv` zJhc2>zX_{(TD}5tm1$eiPyIiI^2bGq_HbBakg7uE#M-zh?C!o#rBpFO8;^DOw9#@x zjQPFNyq^?%zp;vnF6M^muTTJehLcNv>6cY`

ossN4Q)G^6hM)$CeBdyeC(hAIL5 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%0DareDBrhj+ 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

=4tBCRRrg}W2aZlQuHBPE*V6aSQIJk_e;j$c)y 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�kd^Pe~J*6sQD*VJ_m9-J&gR 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%0DGzp}Aby8)WYNAjmzzvVnDK&f`v}qzYxU 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

5zXH{xA)NF6ZMK_ZL7ph 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

1eJ>YopuGVdIR5m4G$xjgA^5dNV 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 z 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�{tbn)bVBl_r4(1TQC_ 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⋙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


nBM##RxTzv$|}Ak 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≧tuQqR2C2Lh0eY?v< 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�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
(?mC_Wx2aQb^|(y=b?uh+TR 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

N6p!qC~ES0Zh7{rC7>nf$~5~h+u-3tBWEs< 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 xxva^+95L*Vm(-Jq=w8&5 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

lmZtOy@aK1 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�N@I- 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%0A+A3UJoP#i?!e+WEz;y=N&0U5Vy2b zv(Q&`Ej~JkOOksW@LPLvpe+@Ctmv>UGqnje!c*R~r+6yARrsAvGaYHO{hC)IOqp(- z96U#4Q6=|qhltXE)70Sx=TkhB50x+@6VFJ>?0X?SaoN%K*qgC;br2Mu$PK!$@As1@ zBh$jYt+0e4iJ*T!fER?|hBVo;w{M0ZV31;%zyZ~Z%=79U!qxK_MW>og@Evs%1Df%U zidMbyJaILQdUnj-)F9?BykzWXT6t#tu;n9aM?6aRa5~4l%fwnS&&-lrk($&nn~07R zPvGfx{J{ogDpTW@mOcSx=h>Vzn51BdX^Ht~RD0{wko^M8`hCZBUu~Waiix#i|6$v1 znax94F3bTQ6x?(X*KZtWLq^>B{hr2-f4_)*jO4?YwkAe>{|_Tq75bbNFy=H{%hUZP zY+&iJ_tC$DR$kVeUtQZ|H#p`{Zk(atDQkHwt;%n@A*5sz;f`nzb*+9Cf^(FV`!Nk@ z`#W&lOVb``49$i)DW*es1L7LcS>TT`&EoAfX`n=kwO-RKF3`eE0Q@IZaA|nV!f{(B zJ{qxwQz~sU%!&uAzGD{nxLYqYV=u-jiwfB) zc>eQ@4VfqX1dExDAJ;z)R7d5K0veQ4BP2E+`Oqvdj8ntF=SU2B=8X*25Q!n@_^GMRZcZN z+{o;D!Pt1A?5*6{r-e=XWQCW%!{kApHNkKUUQ61TH->yWcb(4J?MX=2EciYFK?~!? zKW$sz%FZT?$kpFz)8MI|P;WxU!kGfeIB{IjPP4zoARYi~CdG7xUCegvmCa+DuO-$& z^Kxa7XHYk6sy`eT$AOff3BZ1*7X#f0{&pPzhQzS;0%o?p>;K_IOAde^IS$+PI-b%v zDN`bhGxeo38JEo(?x*(295#QqVAY0!+lKll4ymyOb!0~DIAMl4^*Syx3}SdD^gR+C z4#0`tZ!}&~jQVC-)+9pxfDwmFR6?}+-tDd=F~OK3*mQw4kaI(i>d zulM)22`q>|g-`t&DZ$-~v9^LxsG0-M4&lHsQ3*y1wjri^tU|5>^~E5uZ3YQa+r=~H zl_GiLG-dxcedspkn5GPi;+DcL#g@#q*^f%DYoo-|sQ_e~DncYR zdzgn6GfRXpG|*+lNbPAAVG8hIOzMZIy@rXOxXhH@BWaP7NFC+g3f5@-(FNC6 zsXNL#!Q%H@%tXcCOaN1~DnOif`~UMnd_4~0yZ)zx_@)2#Ab#oV19P8;NT6c!fT~(> zA+&pPh||FKU#9KNG!VrZMufYMXnx9vVdeSYCh>MjLzd07>UmX=boqfZQ?rC*cMb*^ zi4veV$;uHQR8)PQ*Ye;{;z9=m6h^~t$tDU?2LzAe1+Z|t;Ie>Z*{YBQRAZ1RtgnhW zOiPYeHwXGhjVZu=aEt#3XbW(JQ1wWQcv3?-9?Rw)>2)4k)7!qmRp$wEsXGk7O?%bQ zk*x9p654Y#*W8hH!CLsOZJ~Slvh0%TaGb%{ zaoYd}eo`_8t|{(rNopn$7Re!4m{}c~y^7sYmPxb5@n!;#U?RP$KSsqm;W>%B{vi0t z_C0H(1o$Mee@7$~L3bb|)%+wmVao9U`%(+B1)0`ZmaKFMbFfBs$635#gk}K%XP|wK z2&g#4(PlR$$mQL8jr}o%no2SaP*7`4sRGLd#W8=0YTVw1ZT2EOvpncfVlWag1q3vo zS40_@#K!0f_C*(Wm|#iYmmzw?=Pjvj*xau$8%I&I48 z$n^KL(3Nynj)~Joe#Z@%sP=N}l&q&WF^~ren1%~l9^eW=7-=_iPOJjWd308}Jk&y4 z2i4bbOWDVquY$6i<8R2+Cvhe}dOZvUH=qTtFsgIJDK^_0I@Dm2Iaez+%}wE80BBJ~ z$g6(0HWrV|-*f@93;W(*5}K%ehUpH`-k@4M}x%B-xYUTgE{sS^0*I2;&FbnnH05F z{f#z)gH)0~Zu%=a&0Xa8*>wrL`tQi8FMhwotqX;&+b#Vj1ivSu0A;Na_?g&_1_I@ ziR370C8{+qY2(&Qg8#BB^lU#~Z}MwEhb)(xIF#z49hM{bYCN$S_144*^A$jDl6hO| zD{}uhh-QXr&(E;@oyhh66^QKeoc(Vp?u;Ds*2S%S%h9X2=zPEBC47mR0UaUB!2{b% z8^8*a_P3_L!<*E(+{D4S!|vY{=iof{hs*nk4P|x?bu>ra6ik|m=XdyFdsmZlFCrZb z(#?_!e100pQZueseSBEn0vA+DK#|fWg^lP{vP`=WKg#S{HUqdr zfL;PUH6}fkvfv28QPsPJi%lZuIzmCc-v^UMXm z4Pl5&N}_pN6D)N*m?ktEv(A~L2))7Py{iYn_}3&S$il_X2&UmO&%~d;*wXrz_6E=Y zGk_*&k?G~E>twGDFKP%)aIN*K z_=w_Ug^wx4T^s?8!|jk6-a{oE-fHuT+ zWQe345lLGa28QEJ@wZrVah1g?sa4*s3wD}-_LfjgmSCuWHUVIiHGh2874l0SR9 z+3r0IAGf{(kY4I|mPsZn;H2LN)uA9SX$!Wd=fd>1-}UkL?aA7pC#Q6>G{d?Tceet# zcKN`SlglWj&W}mu+_`ac0Vg{pIEjm=)uT@2(%9obmgJv?ukf}Ln%sLSoYrshFNAhm zGz~z3hYV({eE<$eI3PE3OJI`~@8WIk@h9RWjYe!1n}%M6$ib@Jp`5=q{$Uhl zpmMPlNU=wNmPei9{KU096YG+YzB=H)j-aIf2E96U ziW}20M{5Jsdr0N*m$jR1Fi6$J-!yjk?ALq=!Q*23TYlXjV4detQa5@JS`^-)<0N=qBsxOIOT$yCximZ! z=oG8MaFs|2IZ~ruKBVXP4V+-`e?Eh6$QgW(|8xew`M;jQZ+?9xo^s3=&6_cy*O7V| z7&mpidTNQIp;-pseI0S+3YSZKTTLC~Q{j?Yh!UzFMI5Vogf0ulV7FT2`U)8n9KXcx z`-xnWmcj|1Ltb;iX3h*4)I+46#OGr{lW9%8N6^s#?si?79)m`ph@7wBlFeddm5(7) z&DvhHIrW$^Ng9v1Htk}N1xi6X&T+Z!bRe07t2n3ICWYo?F<6ZepPlN7sBcBYiFgXL z9b2_+e`T-PE{Kb>L=^E5S=GhV3YOH97Vg5f>_-GTD#ad<6R41RiYBc=9{yd%I(`>V zxua~jz}59QJwxj5S46}7aIsijym2on4hsh=8qu*wS&sc1rrB1MnJiK*M#RxGe0xs3 zd5i|}Zp)@6-*pgS1Are=boXkE5(jOFXbA8i1dTdN`_!e`HD(xQ;@*-(5MbtOf0MA( zTs_Q9zy|Prd9`?T(RBD$dGMW^#vjK2z=r~&!KKv4+Hj-NqaaBj`?LW)lw}&}$eQ(N zfL9@Yj0YyOq%=$SEi?c|U9e|t(frgbm$D$s$4kz^i~k`%S5fm#4MxF4UIyYnlmJH# zq!6jx@tZLnq{*QFo*Up-t9?qPZZ+ZaaIBCIPaEXvw7Ar8=(Yt~c;~|_Mdx`c{$2!U zkrhLNV{s#Q0X9Uh+Y+UPb$+97rcR;T`Mpn>J5ZI$@9vw?u7>>CSqCBqZF&)?=nL% z7<3hN40sL76DOj=e2Vsu(j7@I{Ek%kR7yo}gk#EF_e9!;8 zD{37?hj5Jlwr<-;9?}4IHmL4}c59j+U0CN!QydU9zL_X418%nu*8f0NiH@lCL0P!+VJqy&-Q2TbmivnNzLkl6;&U-cJ2U@XX*g2E+j zw`bNt!k>2qBy#Z_X>7ynEx~@EJbr)k57*k5TOECwQg=+_Rj4wXH0bt#aS$g3eb7Ju z!@5RD*%1WWwIuyk`=x1f{hkJqQD|OFG$HLyd=C97mnGdPE(XCvGg^b%U>1_=vo)>& z8aI{rzD^2u`krt}Mu{iuX zapICc*8%TJ z_rnQlnpRv~c%Ugs0`w!P#=gK%VaV5)n0T4dkt(RvMe5gu4_#4~`{Lfwn%k_7`NQAj zsJAbYG&pg@G<+m;3|FvX+{e5nye9#Ep5LCF@(riIA3SMD-FL$qM3l&mHj=kb8q)2> zQUkO9`3$}>XYjrL(;57V|9S?$f?o$=zn+;8G35L5CPOFi^WVCS1;ogKg^1s1&S7ce zc1ep>$yyZL)&@5`YElf+2>;mJ1{9*yibw%~)%jD~MuAjWu47 zwUax-py5sy%pwC_L4fD(1j&| z?bbw$vs`@)#K-%xgPnt8XQNNa)eY}Gxih%H+C|IEs7C24>6R_p5JkFL{2}f~R2*Fi4K#@Fxa^I|A+J+nv0$XO%AZ4mf zK-TpigltD@#~>#;*1~84)Dx%aB?Jg^MvYvmH%UqmaP9)Ai}qhI)8m)U1p-b|)62UV z91Aw#3wt=*#I8BQ)*nh?=eL>d0~gufi>sH+O^c;Qf<%zQ&ut6zjj%FekEOH9eO4A^ zTRK>acN>x{{H9ABGr@du6~F`F(td-)E|Lx;;O1G=M#%bvj|Y<6=Ese<4Y~{iJ_XTN z$L{{kwO9wz^XM~8U_maNIwa1BYGt6_dqgoUV0l4c=|KG*tRL-=qYh{pT`tb!rM1Fi zn0ZGVRqi5kB}sqXFUdaWIBlcO(=79odbY`@;2AN7-BzEYFIe#8N@1DGuv6?iwqeZ4 z80~4)^?|=j<6?m?5PSUnl`V=jrjh`vjk>#99oR{IFnyK%jmh~`oi2R300RSQsuO{jVXnI3jWI@}KjQ`#oyZ(PZgm1zjeDDAJ7gQr|GXs}0D6MH0QV+U5i5nUt zVFj{y>T{CW5v;KeXqHR8d{dM=is*q9w$xK69<3eFH22FwY_JVJehj>6cK6Iq9R3wT zAHEtz@7|@+iEtG0SQ^-cNF7Kc?3~G0G|WA1PEZ(OasWT|&g#D{z^m1Zbfs@i0Bs?qLy7&$-OOcNV{4rB0fb z%rfF2ea&6`8^0Bo~u(WC23S7c$wcl5~s~YHDhL)IE7Hb;NI2=+F|*%is|#T`z5zH-L~xF=0plXsG#5J z8HnN<-v6F<^6FjP!Tt~IHAJ&xh{ne@BN)-TXI>Bsc}2X_=e7oD*e%k@Ec z-cx4q#s&hm$V$xq-6EUn7k8R3%I?hXBSE zmantJAXLfpOCtSmLT~HL6dRPxCly<4!vz@i2_!ZMbZol%1d!W zo!7<1^x4!l;w1`0*7Qkt;dD-kQj%6X+cw7&SVXg8*C}1GB|Fcz;4)5zC%9h>Fb-j> z7!P1OSWYxkk$vV8`vJXR7ssT!WtJt|S4Vy8T6p1Fi{cvpkB3nWhw**>@0-yO{AqR) zYN!V+nzf@~$KlYnIujU)X5}QfX+|@wPzy2Tf!B|o?XOlbZI70{mm9YcSQ#^AhdMT# z%Tn3w4mAla<@pfm;4Nm8R?yJGvH?XD1|(#{;lKIK1?e<0S zvkaEobWE{AWo|@)*ULGQuj=(&`b~Esv4IwNBR0vEGMg;I#C+PZlLFx#%VVcV@U0$p zZ-(ma2`AYf;ypbbnRfdsg=+hIjKp)LyOFC~4FMyfq^_8Ef@Gtw{o0tGhqO@8NmbK> z-=@yYaBPT*NYKTl8XX2IW*vsBAj=ERJPIrf?1yNSJ>HGu_}fe3bfkQFrb(n@7>gr; z6RWj|{ST;qx$Wyivz}`{szF4_nMJS$1b`q#2d~jbFs%|=LvNs42hZUIQ2dBcAaIl^ zMJ$(^Muxz%ZrvBqMl~=M2)n2i5>J7LFxmEgqY028M8BIwvpv*u8wrrN9<1K3k^ZOV-|Z> z5@fL5?kil!K99y2I?;^Se4>03p7~h;pv}5pyJoatz@Fq2R%em_W$u{e3@M@@Qq+()_2@cfT0Kp#AF<@|XOYdOK#SU0O9F_?$9seN zhK2jvGcLDFjb)#YhPF@i1avQ<5q57j29kz5=4h8|+9KQ$FwrtKHT^%IJ>l%V?|(Xb zU-w_n-q*dp8O5Fkf}-S0N(>?ZO$FT3pj{^YS~ybwCZrbv385-88gms+dT|}WxsdtL z3@19=l)wmi9dro56C%tk_Jz=cAIyUaUi-~7!!4iV@40!Ce9tp!Bz}`AEU)o^!c-TI zr2w3`BvwIA!RBih9^4>nIdzIsY}*;kjUWv!3KU2Y=vqBB6S?nQgBAHSn6PqSF8_xi z4Z}eL)5q!I-w1mzsUbnR-*w5XcHT16uzHB4_@qAiL(gqag2<#pI)ny%amb+Ok#m4CM*5z?9qm>AO~kxWXJXhfHx*NiCyIZZ(+=b!fMZS48AMo4dx zhsrT7;UE#ZkR%cEuBFRx7DTbmwVH026?w-8 zBp5Nn;JBheTeE9zS~@tzZ|wi3Pg2`bY3QT^yQv98G*0SLH{obAx)qZpk`L+ z82|SLC!mRQ>bA_OBdIZJwfmf=5k<(qDx3X~MQ_SEdq2y%fmMwu|J%%QIkRe029P2U z@(1;~7R)60xYO=H?+P^f`E zam`$Um&$6isqm-G(Qm?zmx#PieAXeW0|oKf5mdEbPc{fgmo7-c&&)OsV@p`uw-YjJ zS(mrK)=H|mEe#)T>jjov9Z&vtA{#`xOOhtuwkfe5|24>wx)>5V{9nzpSoR6PqFZQy za98?e@tb2aUgPcm&u39Ni|_Y;BWs%Py@E^UHopTaFb5q!e%kuo=w%WoS0d>@aFA(J z$Bx)~~ZRTuEl>~FuY?QP3yA?XR6 z7)e+5j;n3{!9$dJ=ZtNNJ4(QwdDn~L$J=I;+Om%x-3C{b=pTD)k**OYAB!{g`<#=2 zwnobA=R(keCWgTz4GAUSqrd-{#61jm>O$294c;T_J;SU*%FCNWstpJ7__3-RnEXA7 z9sJ%J7v#5+I&y2SLBtzhk}UaMT_Q;hkIXzJD8Ic8PW7E1>|1Mq>9`-jfm`S9-zBWe zkBcUmF&!pfBoD{a;x($}l9(I3Jo4HJ$Q3n`BIh!TshO3eGzMie<0x@Fl8u!86Bnw+ z3u=SI>;`c$UmZOREdd??0PxxEEfywqh-Na6YM%Yip}neZRb@$zaw#rLhDr!So&mu9 z;jcXQqRJ5KT~tCYnQr|aIlBq9%kDWvCtS9_fkb+{dYQd8c?mL|h!Z%aa+k&>G_y@s zS&6uL2f<3Y`irz1lodeG{o=~`T2`HO(>}o(qS!=!Vmo%N1@x|r(GYDhN}!`UWpidm zD~UEvLl)0XkfJhsILmCkjw?1qxNI^msOV9um3qT!A=@};>}6EqyVg8z4_UeJ>q!f< zP_Z6ab|y$(uf`Vl#6#oIBEgUF|9trVh{N~(|FcBl%7tC{5RFQGTu;$}xBp2U|% zpA0IQQdiCjtx2Ymso77SR}scx@@5CW*_7##y&-B`L2;n2X$m-KAjkV>X&nd6c*>k* z{fl7$Dp)6UXG~qU_*!Jir3IA;%wT`f>2Lb6%5@BI*u?GD2regNUy&|HsDdob)xNr% zc>FN}B|V&LLWyb-u7L$V;E^FnHk#=zf;3lKCx6YB=Kh-duHoJhK%D7guq zJo7;J8Jw+X?__8?d<>Zba8{VzrOY>9?Mj7U3odmNJy&ZP1UJ)$cm-rXq+{7Dd;Wzu zG{=XMY${`X;}FGGI3LLzn5HzNs1z(VW;lGVUH5)}@1X;-csam((E_2w_4%QOust`Q z*YpcqCJoInA+NH(+cOsVVS}p@P>@FDs{T6_L+-5i8$-6Li#1>RIUq+aB9OncK;n@& z?^jvyn?1;5l+|5HIE7c5ahMT0hl7v!HwIVeZoC20|M?L9F^BL2{_pIB)JeE7Evrv?cY=PJA}&6sw8@ zmB0G=Iwo+#n}#jkKp?$q05_Ns`U>=x2fWg@W61p&h{Ha$76@Nmy;u9UV{-sUu!F;< z0Y;rBUH7-Z4x_(?Dd@hKX_L|&l4kA(#SwnGc(tp&GE}fxmodhq+-FU^j5C9ZGiaI+ zCYi?-BaJQH5k{2sZQ52}&j#4)4C99WF*S3P%(SdmW;Z4KyNVgmtUgTW&`>b|h_ZzI ziI|@2A_b-Q{^+<8rdv+67e_uZ$BbC*(}L`m$u1THLb5wM_{}{j6~(~^y=P&iBerb-t@I}iE+n})W?L|dA2VQxbcOL0d#b4_8})lqGKZ^~x;nkf+?O&^L>+kFBH(&>`> z)FDDhSholWjI`Q?~BB1k4UAKVJx}F@Dm7swd3_=TFR=C=)N1q1N6M zldJw_moSKBN((K?$0U%GT2*R6?1vipE$2n~chd;HIwY#i2n3YE`Cr=voOR9NXsYU3 zh|5o>ARKAtD+$4(G@0^oF121ftDEB`kdztm2~cc-(m9HJZ-3EL1S}uK9(svA zComCN-zY7nOL#A!$+kK2nIYO84m)5uDf%?tl1}pQK;-Jp8XSE4<4kW%_UL2ah%b+1 zV{O^S08!PtHaJ{ev)+@)0G%3Q5!P8)3`%5@K*(XcLs-xRhhOz|6xR&K5%>0Hftgv` zt*7cl-s4}inZfuYjOX+23!?k3#`dqae=~yB#kThcnB~>qxz?G$i$JCJs1*6M)*!XZ2CAA_Z!j_w{k(JHl1pUrzT!Xl{hi09 z0>Jo?_`t>1I;I}^$rXI88D7wl#v%ip}gxR!K)UCP=iYzCVfL+fqZtk`T4e`tIHe+DJw++JDST5PatAhQR zBlzjz+s^-d0RNN&_(A{a0Dj?rJ%C^M`qxW*6r$6AIAak2jGMM^f|lxPFVI3H9eb#2 ze-k(8cBVb=RsXjTH~|=2$RGA<{|!nP!NaI}pov1J-{&|XD2U~WkOrvLUP-K9cw*~3 zu^;;TVOjKlXQ`C56sgHLm=|MrAai!W5M>4p9TvG_v)Ga;kt0SpB(S+UFe(T%@WeDM z54f@pZXkh2!``FGF5iM=`gI;ilqrtvjs!Nf59tR0y~nJbD$7<-P&wdtUqP((m|Ki140tSpLH=FMxaDA)x+)~&TUtp0w{G|7A? zGwK*^gcxp1S_$)Awhbz7PI?;`83dY1C#roD;1V9+Fb*X}SK| z{G_A3^>4eR*0O^5aaqDXKI-2lR1o=nFi;vzn3@FrPktFWlj-dayQ%ZrdC5{U@r3i5 zMXrY?tI|Yh6Q&m2iPCq zr<*+3_45oMndx|5TWY&28wbDJJU^7U1C7|a{n5n*CL-J}F2bHAWn$n1;L5Al3cuyH z!d5Vfe~emd_=Y`l@q|?4uN`0VDTRpWoICLSC6|x{L*e*)HIcM_5FWsyCAH2ivr+d1 zLVhfM|HJaN8t3_HE*>kXV&2Ib>;O8erGSx*g8fxvD;}iZ4{3(+u7cEW`8Pb8)|$8x zR+m|T1qHMTi%MvM%nvlco>m}d5dJWn9qMd9dCatK=EL6#-sf-qzXKj`Nyk5gj$s#H zYLky=7xfsB9=1a>jTa>C&D+*VAt4jfh6G>UBcY9{EY@}*Fq~eyE?`k)#OxIt&odo3tiu^}z8YZNJ+Sr1B@0Us zzvp~(kooK{r(t48DDIMaxgmSBMnMqQ`Zs4}G3&=>)coY@`o#pMA^`#%(GBT$5*nEk(-`%+CZ=en-ycz3L&zt?^ZA7#N6E)ZKc z+#*@Vpg7%C2$~I#X*Z-u0l))Ji?e}z1ndJki9GwviW#)#WIk`5=RF5;M+paTSnm(6 z`b@EB%e#Fvl*i-eDBO&h5Ctl;n3`5a;z>yGT$44pOoSo9G^?@DY1JGqE!+fdF-uEv zZ0Yw^)bu7OKX)F<#eOq!PqK)cyHNuHIFBe^y(35~9c{d{AC|vO6G#aV;1UjZVMB|F z3^_-(aqEk3f(X`R?S2JTMY#?9;Y1Pn6TVT2e>1P4L9u_27|W#=UG4r_{vo4zE0^(GZLwD9}YmbLf-YUL@;@ zh3B@8Bu#PQ0`5%-^LF*9rDhzE;MR5fse8N9V%XN(*q&~XwV6tZmA``fFOdvH1Mvq$ z1Zf^?92YxgFI3+zUWcSsM?A31Tr>E5q{W!{@Zue|ZwE-3T5(-MJvpjrbN4oLk6MCx z|33#N{`l88cOUwn&fS;&*K_w}+?h53(IbSVJziNBl3)!*l>{+|lrRJA9$+9=U_VbYK7l4ldQcw#&f|{∓kZd(9={ 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

EznBGV(434dWrMi&e$OuVlmgW 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%0Afk4jzs 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 literal 0 HcmV?d00001 From 75ec40aa14c5652e5ac69ef4554d93b723390b9a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 24 Apr 2025 21:30:32 +0300 Subject: [PATCH 0488/1064] Added/Updated tests\bugs\gh_8485_test.py: INVESTIGATION NEEDED. Weird affecting on functional/syspriv/test_user_management_in_selfsec_db.py --- tests/bugs/gh_8485_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/gh_8485_test.py b/tests/bugs/gh_8485_test.py index cb8c338c..d72492fc 100644 --- a/tests/bugs/gh_8485_test.py +++ b/tests/bugs/gh_8485_test.py @@ -34,6 +34,7 @@ } """ +@pytest.mark.skip("INVESTIGATION NEEDED. Weird affecting on functional/syspriv/test_user_management_in_selfsec_db.py") @pytest.mark.version('>=3.0.13') def test_1(act: Action, tmp_file: Path, store_config: ConfigManager, capsys): From 5bcf8183480ab24f3504bdcbde3452c5b2839637 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 25 Apr 2025 13:09:39 +0300 Subject: [PATCH 0489/1064] Added/Updated tests\bugs\gh_8437_test.py: Added temporary mark 'disabled_in_forks' to SKIP this test when QA runs agains *fork* of standard FB. --- tests/bugs/gh_8437_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/bugs/gh_8437_test.py b/tests/bugs/gh_8437_test.py index 8591cb38..457b7b11 100644 --- a/tests/bugs/gh_8437_test.py +++ b/tests/bugs/gh_8437_test.py @@ -13,6 +13,9 @@ [18.03.2025] pzotov Confirmed crash on 3.0.13.33798; checked on 3.0.13.33804 after fix #e02eaffb. Reduced min_version from 4.0.6 to 3.0.13. + + [25.04.2024] pzotov + Added temporary mark 'disabled_in_forks' to SKIP this test when QA runs agains *fork* of standard FB. """ import pytest @@ -31,6 +34,7 @@ 1 """ +@pytest.mark.disabled_in_forks @pytest.mark.version('>=3.0.13') def test_1(act: Action): act.expected_stdout = expected_stdout From e0d961949aa0048b3969150eaca13d4c910dd49a Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Tue, 29 Apr 2025 14:58:12 +0200 Subject: [PATCH 0490/1064] Exclude local and private files --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f146d8d..db5f2b74 100644 --- a/.gitignore +++ b/.gitignore @@ -134,4 +134,10 @@ dmypy.json *.wpu # Sphinx build -docs/_build \ No newline at end of file +docs/_build + +# Other local files +/dbcache + +# Personal local files +/personal From b434b3453d7f3a54e5047f4130e2bb24879605c6 Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Tue, 29 Apr 2025 15:38:03 +0200 Subject: [PATCH 0491/1064] Release 0.20.1 --- CHANGELOG.md | 7 ++++ docs/changelog.txt | 6 +++ pyproject.toml | 92 +++++++++++++++------------------------------- 3 files changed, 42 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8af7ed68..b27c9081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.20.1] - 2025-04-29 + +### Changed + +- Dependency on `firebird-base` changed to "~=1.8" +- Updated `hatch` configuration + ## [0.20.0] - 2024-05-09 ### Added diff --git a/docs/changelog.txt b/docs/changelog.txt index afcb196f..9104936f 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -4,6 +4,12 @@ Changelog .. currentmodule:: firebird.qa.plugin +Version 0.20.1 +============== + +* Dependency on `firebird-base` changed to "~=1.8" +* Updated `hatch` configuration + Version 0.20.0 ============== diff --git a/pyproject.toml b/pyproject.toml index 0288846a..5a568146 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ classifiers = [ "Framework :: Pytest", ] dependencies = [ - "firebird-base>=1.8.0", + "firebird-base~=1.8", "firebird-driver~=1.10", "pytest>=7.4", "psutil~=5.9", @@ -64,6 +64,11 @@ packages = ["src/firebird"] dependencies = [ ] +[tool.hatch.envs.hatch-test] +extra-args = ["-vv", "--server", "local"] +dependencies = [ +] + [tool.hatch.envs.test] dependencies = [ "coverage[toml]>=6.5", @@ -101,63 +106,13 @@ docset = [ "cd docs; VERSION=`hatch version` ; tar --exclude='.DS_Store' -cvzf ../dist/firebird-qa-$VERSION-docset.tgz firebird-qa.docset", ] -[tool.hatch.envs.lint] -detached = true -dependencies = [ - "black>=23.1.0", - "mypy>=1.0.0", - "ruff>=0.0.243", -] -[tool.hatch.envs.lint.scripts] -typing = "mypy --install-types --non-interactive {args:src/firebird/qa tests}" -style = [ - "ruff {args:.}", - "black --check --diff {args:.}", -] -fmt = [ - "black {args:.}", - "ruff --fix {args:.}", - "style", -] -all = [ - "style", - "typing", -] - -[tool.black] -target-version = ["py38"] -line-length = 120 -skip-string-normalization = true - [tool.ruff] -target-version = "py38" +target-version = "py311" line-length = 120 -select = [ - "A", - "ARG", - "B", - "C", - "DTZ", - "E", - "EM", - "F", - "FBT", - "I", - "ICN", - "ISC", - "N", - "PLC", - "PLE", - "PLR", - "PLW", - "Q", - "RUF", - "S", - "T", - "TID", - "UP", - "W", - "YTT", + +[tool.ruff.lint] +select = ["A", "ARG", "B", "C", "DTZ", "E", "EM", "F", "FBT", "I", "ICN", "ISC", "N", + "PLC", "PLE", "PLR", "PLW", "Q", "RUF", "S", "T", "TID", "UP", "W", "YTT", ] ignore = [ # Allow non-abstract empty methods in abstract base classes @@ -168,24 +123,35 @@ ignore = [ "S105", "S106", "S107", # Ignore complexity "C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915", + # + "E741", + # Allow relative imports + "TID252", + # Allow literals in exceptions + "EM101", "EM102", + # Single quotes instead double + "Q000" ] unfixable = [ # Don't touch unused imports "F401", + # Don't change single quotes to double + "Q000" ] +exclude = ["*_pb2.py", "*.pyi", "tests/*", "docs/*", "personal/*"] -[tool.ruff.isort] -known-first-party = ["firebird.qa"] +[tool.ruff.lint.isort] +known-first-party = ["firebird.base"] -[tool.ruff.flake8-tidy-imports] +[tool.ruff.lint.flake8-tidy-imports] ban-relative-imports = "all" -[tool.ruff.per-file-ignores] +[tool.ruff.lint.extend-per-file-ignores] # Tests can use magic values, assertions, and relative imports "tests/**/*" = ["PLR2004", "S101", "TID252"] [tool.coverage.run] -source_pkgs = ["firebird.qa", "tests"] +source_pkgs = ["firebird.qa"] branch = true parallel = true omit = [ @@ -193,8 +159,8 @@ omit = [ ] [tool.coverage.paths] -firebird_qa = ["src/python", "*/python/src/firebird/qa"] -tests = ["tests", "*/python/tests"] +firebird_qa = ["*/src/firebird/qa"] +tests = ["tests"] [tool.coverage.report] exclude_lines = [ From fa7b69614c4fc2624300bd6cfc15982f2f07008d Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Tue, 29 Apr 2025 15:42:31 +0200 Subject: [PATCH 0492/1064] Add missing updated version --- src/firebird/qa/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firebird/qa/__about__.py b/src/firebird/qa/__about__.py index bf7b2388..40e23a9e 100644 --- a/src/firebird/qa/__about__.py +++ b/src/firebird/qa/__about__.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: 2021-present The Firebird Projects # # SPDX-License-Identifier: MIT -__version__ = "0.20.0" +__version__ = "0.20.1" From bde93e32c2981259d6ce0073d7b5719ad622203a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Apr 2025 16:23:53 +0300 Subject: [PATCH 0493/1064] Added/Updated tests\bugs\gh_8532_test.py: Checked on 6.0.0.755-9d191e8 (intermediate snapshot). --- tests/bugs/gh_8532_test.py | 125 +++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 tests/bugs/gh_8532_test.py diff --git a/tests/bugs/gh_8532_test.py b/tests/bugs/gh_8532_test.py new file mode 100644 index 00000000..f695b40a --- /dev/null +++ b/tests/bugs/gh_8532_test.py @@ -0,0 +1,125 @@ +#coding:utf-8 + +""" +ID: issue-8532 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8532 +TITLE: GREATEST and LEAST (SQL:2023 - T054) +DESCRIPTION: +NOTES: + [30.04.2025] pzotov + Checked on 6.0.0.755-9d191e8 (intermediate snapshot). +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + + select least(654, 987, 123, 741) as least_01 from rdb$database; + + select least(1.976262583364986e-323, 4.940656458412465e-324, 9.881312916824931e-324) as least_02 from rdb$database; + + select least(0e0, -0e0) as least_03 from rdb$database; + + select least(true, false, false) as least_04 from rdb$database; + + select least(timestamp '01.01.0001 00:00:00.100', timestamp '31.12.9999 23:59:59.999', timestamp '01.01.1970 00:00:00.000') as least_05 from rdb$database; + + select least(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727) as least_06 from rdb$database; + + select least(df0, df1, df2) as least_07 + from ( + select + exp( cast( -14221.4586815117860898045324562520948 as decfloat) ) as df0 + ,exp( cast( -14221.4586815117860898045324562520949 as decfloat) ) as df1 + ,exp( cast( -14221.4586815117860898045324562520950 as decfloat) ) as df2 + from rdb$database + ); + + + select least(null, null, 191, null, null, -213, null, null) as least_08 from rdb$database; + + select least( + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --50 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --100 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --150 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --200 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --250 + ,1,1,1,1,1 -- the last element (# 255) where result is OK + ,1 -- adding this element leads to error message + ) as least_09 + from rdb$database; + + --------------------------------------------------------------------- + + select greatest(654, 987, 123, 741) as greatest_01 from rdb$database; + + select greatest(1.976262583364986e-323, 4.940656458412465e-324, 9.881312916824931e-324) as greatest_02 from rdb$database; + + select greatest(0e0, -0e0) as greatest_03 from rdb$database; + + select greatest(true, false, false) as greatest_04 from rdb$database; + + select greatest(timestamp '01.01.0001 00:00:00.100', timestamp '31.12.9999 23:59:59.999', timestamp '01.01.1970 00:00:00.000') as greatest_05 from rdb$database; + + select greatest(-170141183460469231731687303715884105728, 170141183460469231731687303715884105727) as greatest_06 from rdb$database; + + select greatest(df0, df1, df2) as greatest_07 + from ( + select + exp( cast( -14221.4586815117860898045324562520948 as decfloat) ) as df0 + ,exp( cast( -14221.4586815117860898045324562520949 as decfloat) ) as df1 + ,exp( cast( -14221.4586815117860898045324562520950 as decfloat) ) as df2 + from rdb$database + ); + + + select greatest(null, null, 191, null, null, -213, null, null) as greatest_08 from rdb$database; + + select greatest( + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --50 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --100 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --150 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --200 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 --250 + ,1,1,1,1,1 -- the last element (# 255) where result is OK + ,1 -- adding this element leads to error message + ) as greatest_09 + from rdb$database; +""" + +act = isql_act('db', test_script, substitutions = [ ('[ \t]+',' ') ]) + +expected_stdout = """ + LEAST_01 123 + LEAST_02 4.940656458412465E-324 + LEAST_03 0.000000000000000 + LEAST_04 + LEAST_05 0001-01-01 00:00:00.1000 + LEAST_06 -170141183460469231731687303715884105728 + LEAST_07 0E-6176 + LEAST_08 + Statement failed, SQLSTATE = 42000 + Maximum (255) number of arguments exceeded for function LEAST + + GREATEST_01 987 + GREATEST_02 1.976262583364986E-323 + GREATEST_03 0.000000000000000 + GREATEST_04 + GREATEST_05 9999-12-31 23:59:59.9990 + GREATEST_06 170141183460469231731687303715884105727 + GREATEST_07 1E-6176 + GREATEST_08 + Statement failed, SQLSTATE = 42000 + Maximum (255) number of arguments exceeded for function GREATEST +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From 766f6ed471931c869067018bd273a1ae17283547 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 30 Apr 2025 16:24:55 +0300 Subject: [PATCH 0494/1064] Added/Updated tests\bugs\gh_8532_test.py: Checked on 6.0.0.755-9d191e8 (intermediate snapshot). --- tests/bugs/gh_8532_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/gh_8532_test.py b/tests/bugs/gh_8532_test.py index f695b40a..77431569 100644 --- a/tests/bugs/gh_8532_test.py +++ b/tests/bugs/gh_8532_test.py @@ -7,7 +7,7 @@ DESCRIPTION: NOTES: [30.04.2025] pzotov - Checked on 6.0.0.755-9d191e8 (intermediate snapshot). + Checked on 6.0.0.755-9d191e8 (intermediate snapshot) """ import pytest From bf13a19af8de7a7903835aaa6216c2c3e450f4ec Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 May 2025 09:53:00 +0300 Subject: [PATCH 0495/1064] Updated tests\bugs\gh_0310_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_0310_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_0310_test.py b/tests/bugs/gh_0310_test.py index 77a2a072..38a91464 100644 --- a/tests/bugs/gh_0310_test.py +++ b/tests/bugs/gh_0310_test.py @@ -1901,6 +1901,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME GRANTED RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME GREATEST + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME GROUP RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME HASH @@ -1979,6 +1981,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME LEADING RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME LEAST + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME LEAVE RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME LEFT @@ -2540,7 +2544,7 @@ RDB$KEYWORD_NAME ZONE RDB$KEYWORD_RESERVED - Records affected: 507 + Records affected: 509 """ @pytest.mark.disabled_in_forks From 96aed1bd1c55765729042b32c7fd645e7468e722 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 12 May 2025 12:21:23 +0300 Subject: [PATCH 0496/1064] Added/Updated tests\bugs\gh_7865_test.py: Confirmed improvement on 6.0.0.779-136fa13 --- tests/bugs/gh_7865_test.py | 84 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/bugs/gh_7865_test.py diff --git a/tests/bugs/gh_7865_test.py b/tests/bugs/gh_7865_test.py new file mode 100644 index 00000000..0c69fb14 --- /dev/null +++ b/tests/bugs/gh_7865_test.py @@ -0,0 +1,84 @@ +#coding:utf-8 + +""" +ID: issue-7865 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7865 +TITLE: Consider the return value of deterministic functions to be invariant if all its arguments are invariant +DESCRIPTION: + Test uses example provided in the ticket: we check performance of query which has `WHERE` clause + with deterministic function in one of its parts. +NOTES: + [12.05.2025] pzotov + Further checks may be included into this test later. + One may find this link useful (for those who can read in Russian): + https://murcode.ru/search/deterministic/?message=True&topic=True&user=False&forum=2&orderby=byDefault + + Confirmed improvement on 6.0.0.779-136fa13: number of NR = 2 * + Before this fix NR was * + (checked on 6.0.0.770-82c4a08) +""" + +import pytest +from firebird.qa import * + +###################################### +ROWS_COUNT = 30 +MAX_ALLOWED_NAT_READS = 2 * ROWS_COUNT +###################################### + +init_sql = f""" + create table test(id int, x bigint); + insert into test(id, x) select i, i*i from (select row_number()over() as i from rdb$types rows {ROWS_COUNT}); + commit; + + set term ^; + create function fb_get_x_for_id(a_id int) returns bigint deterministic as + begin + return (select t.x from test t where t.id = :a_id); + end + ^ + commit + ^ + set term ;^ +""" + +db = db_factory(init = init_sql) + +act = python_act('db') + +#----------------------------------------------------------- + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + msg_prefix = 'Number of natural reads:' + expected_txt = 'EXPECTED' + nat_reads = {} + with act.db.connect() as con: + cur = con.cursor() + + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = upper('test')") + src_relation_id = cur.fetchone()[0] + nat_reads[src_relation_id] = 0 + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + nat_reads[src_relation_id] = -x_table.sequential + + cur.execute(f"select * from test where x = fb_get_x_for_id({ROWS_COUNT})") + # cur.execute(f"select * from test where fb_get_x_for_id({ROWS_COUNT}) = x") -- checked; result is the same. + data = cur.fetchall() + + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + nat_reads[src_relation_id] += x_table.sequential + + if nat_reads[src_relation_id] <= MAX_ALLOWED_NAT_READS: + print(f'{msg_prefix} {expected_txt}') + else: + print(f'{msg_prefix} UNEXPECTED: {nat_reads[src_relation_id]} - greater than threshold = {MAX_ALLOWED_NAT_READS}.') + + act.expected_stdout = f""" + {msg_prefix} {expected_txt} + """ + + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 801b2dfdfa004091025b530ef7c03346527c80e4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 15:24:29 +0300 Subject: [PATCH 0497/1064] Added/Updated tests\bugs\core_4374_test.py: Removed output of approximate BLR length because its change can be valuable. --- tests/bugs/core_4374_test.py | 41 ++++++++++++------------------------ 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/tests/bugs/core_4374_test.py b/tests/bugs/core_4374_test.py index 53966b73..e1a9a5ba 100644 --- a/tests/bugs/core_4374_test.py +++ b/tests/bugs/core_4374_test.py @@ -7,6 +7,18 @@ DESCRIPTION: JIRA: CORE-4374 FBTEST: bugs.core_4374 +NOTES: + [05.05.2015] pzotov + ::: NB ::: + Memory consumption of procedural objects under 64-bit environment is much bigger than on 32-bit one. + This test was retyped because it was encountered that previous limit for the size of BLR is too weak: + test failed at runtime with error "implementation limit exceeds". + New (more rigorous) limit was found by using 64-bit FB, build LI-T3.0.0.31822: BLR can not be larger + than ~2.35 Mb (previous: ~3.21 Mb) + + [15.05.2025] pzotov + Removed output of approximate BLR length because its change can be valuable: + 6.0.0.778 2025.05.07 d735e65a: 2097000 bytes instead of previous 2359000. """ import pytest @@ -15,12 +27,6 @@ db = db_factory() test_script = """ - -- ::: NB ::: - -- Memory consumption of procedural objects under 64-bit environment is much bigger than on 32-bit one. - -- This test was retyped because it was encountered that previous limit for the size of BLR is too weak: - -- test failed at runtime with error "implementation limit exceeds". - -- New (more rigorous) limit was found by using 64-bit FB, build LI-T3.0.0.31822: BLR can not be larger - -- than ~2.35 Mb (previous: ~3.21 Mb) set list on; set term ^; @@ -80,7 +86,7 @@ set term ^; - execute block returns(returned_rows int, proc_ddl_length int, proc_src_length int, approx_blr_length int) as + execute block returns(returned_rows int, proc_ddl_length int, proc_src_length int) as begin execute statement 'select count(*) cnt from test_proc' into returned_rows; @@ -91,32 +97,12 @@ from rdb$procedures where rdb$procedure_name = upper('test_proc') into proc_src_length; - select round(octet_length(rdb$procedure_blr), -3) - from rdb$procedures where rdb$procedure_name = upper('test_proc') - into approx_blr_length; - suspend; end ^ set term ;^ commit; - - /************************************** - - 32 bit, WI-T3.0.0.31824 - RETURNED_ROWS 119154 - PROC_DDL_LENGTH 1072455 - PROC_SRC_LENGTH 1072395 - APPROX_BLR_LENGTH 3217000 - - 64 bit, LI-T3.0.0.31822 - RETURNED_ROWS 87379 - PROC_DDL_LENGTH 786480 - PROC_SRC_LENGTH 786420 - APPROX_BLR_LENGTH 2359000 - - **************************************/ """ act = isql_act('db', test_script) @@ -125,7 +111,6 @@ RETURNED_ROWS 87379 PROC_DDL_LENGTH 786480 PROC_SRC_LENGTH 786420 - APPROX_BLR_LENGTH 2359000 """ @pytest.mark.version('>=3.0') From fb9102ce1bbf8113cd6fcc1968e9d7a8201a2680 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 15:31:57 +0300 Subject: [PATCH 0498/1064] Added/Updated tests\bugs\core_4468_test.py: Splitted output for versions up to 5.x and 6.x+ - see notes. --- tests/bugs/core_4468_test.py | 114 ++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4468_test.py b/tests/bugs/core_4468_test.py index c9bd41ae..af1f7676 100644 --- a/tests/bugs/core_4468_test.py +++ b/tests/bugs/core_4468_test.py @@ -11,8 +11,11 @@ 1. Commented out (and will be deleted later) code that expected error when user who was granted role with admin option tries to revoke this role from himself. Seince fixed GH-8462 this is NOT so. 2. Replaced hard-coded names/passwords with variables that are provided by fixtures (tmp_senior, tmp_junior). - Checked on 6.0.0.660; 5.0.3.1624; 4.0.6.3189; 3.0.13.33798 + + [15.05.2025] pzotov + Splitted output for versions up to 5.x and 6.x+: privilege "GRANT CREATE DATABASE TO USER ..." has appeared + in the output since 6.0.0.778 2025.05.07 d735e65a. """ import locale @@ -145,7 +148,113 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): commit; """ - act.expected_stdout = """ + expected_5x = """ + MSG start + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG start + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + MSG point-1 + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG point-1 + WHO_AM_I SYSDBA + WHATS_MY_ROLE NONE + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + MSG point-2 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG point-2 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + /* Grant permissions for this database */ + GRANT SELECT ON V_USERS TO PUBLIC + GRANT RDB$ADMIN TO OZZY_OSBOURNE + MSG point-3 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG point-3 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + /* Grant permissions for this database */ + GRANT SELECT ON V_USERS TO PUBLIC + GRANT RDB$ADMIN TO BON_SCOTT GRANTED BY OZZY_OSBOURNE + GRANT RDB$ADMIN TO OZZY_OSBOURNE + MSG point-4 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG point-4 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + /* Grant permissions for this database */ + GRANT SELECT ON V_USERS TO PUBLIC + GRANT RDB$ADMIN TO OZZY_OSBOURNE + MSG point-5 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + MSG point-5 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME BON_SCOTT + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 2 + /* Grant permissions for this database */ + GRANT SELECT ON V_USERS TO PUBLIC + GRANT RDB$ADMIN TO OZZY_OSBOURNE + MSG point-6 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 1 + Statement failed, SQLSTATE = 28000 + delete record + -no permission for DELETE access to TABLE PLG + MSG point-7 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 1 + MSG point-8 + WHO_AM_I OZZY_OSBOURNE + WHATS_MY_ROLE RDB$ADMIN + NON_SYSDBA_USER_NAME OZZY_OSBOURNE + NON_SYSDBA_HAS_ADMIN_ROLE + Records affected: 1 + /* Grant permissions for this database */ + GRANT SELECT ON V_USERS TO PUBLIC + GRANT RDB$ADMIN TO OZZY_OSBOURNE + """ + + expected_6x = """ MSG start WHO_AM_I SYSDBA WHATS_MY_ROLE NONE @@ -251,5 +360,6 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): GRANT RDB$ADMIN TO OZZY_OSBOURNE """ + act.expected_stdout = expected_5x if act.is_version('<6') else expected_6x act.isql(switches = ['-q'], input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From 3520e50fd505d1bcc707e1b18b7516687550ad73 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 15:41:21 +0300 Subject: [PATCH 0499/1064] Added/Updated tests\bugs\core_4806_test.py: Removed 'show grants' because its output very 'fragile' and can often change in fresh FB versions. --- tests/bugs/core_4806_test.py | 102 ++++++++++++++++------------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/tests/bugs/core_4806_test.py b/tests/bugs/core_4806_test.py index 4ed8ea6b..720c06a0 100644 --- a/tests/bugs/core_4806_test.py +++ b/tests/bugs/core_4806_test.py @@ -16,17 +16,20 @@ Also, we do additional check for second user: try to connect WITHOUT specifying role and see/change sequence. Error must be in this case (SQLSTATE = 28000). Third user must NOT see neither value of generator nor to change it (SQLSTATE = 28000). -NOTES: -[18.08.2020] - FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): - statement 'CREATE SEQUENCE ' will create generator with current value LESS FOR 1 then it was before. - Thus, 'create sequence g;' followed by 'show sequence;' will output "current value: -1" (!!) rather than 0. - See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d - - This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt - Because of this, it was decided to filter out concrete values that are produced in 'SHOW SEQUENCE' command. JIRA: CORE-4806 FBTEST: bugs.core_4806 +NOTES: + [18.08.2020] pzotov + FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): + statement 'CREATE SEQUENCE ' will create generator with current value LESS FOR 1 then it was before. + Thus, 'create sequence g;' followed by 'show sequence;' will output "current value: -1" (!!) rather than 0. + See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d + + This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt + Because of this, it was decided to filter out concrete values that are produced in 'SHOW SEQUENCE' command. + + [15.05.2025] pzotov + Removed 'show grants' because its output very 'fragile' and can often change in fresh FB versions. """ import pytest @@ -48,7 +51,6 @@ grant usage on sequence g to role stockmgr; grant stockmgr to Bill_Junior; commit; - show grants; set list on; @@ -101,53 +103,43 @@ commit; """ -act = isql_act('db', test_script, substitutions=[('-Effective user is.*', ''), - ('current value.*', 'current value')]) - -expected_stdout = """ - /* Grant permissions for this database */ - GRANT STOCKMGR TO BILL_JUNIOR - GRANT USAGE ON SEQUENCE G TO USER BIG_BROTHER - GRANT USAGE ON SEQUENCE G TO ROLE STOCKMGR - - USER BIG_BROTHER - ROLE NONE - Generator G, current value: 0, initial value: 0, increment: 1 - NEW_GEN -111 - - USER BILL_JUNIOR - ROLE STOCKMGR - Generator G, current value: -111, initial value: 0, increment: 1 - NEW_GEN -333 - - USER BILL_JUNIOR - ROLE NONE - - USER MAVERICK - ROLE NONE -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - no permission for USAGE access to GENERATOR G - There is no generator G in this database +substitutions = [ ('[ \t]+', ' ') + ,('(-)?Effective user is.*', '') + ,('current value.*', 'current value') + ] - Statement failed, SQLSTATE = 28000 - no permission for USAGE access to GENERATOR G - - Statement failed, SQLSTATE = 28000 - no permission for USAGE access to GENERATOR G - There is no generator G in this database - - Statement failed, SQLSTATE = 28000 - no permission for USAGE access to GENERATOR G -""" +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3.0') def test_1(act: Action, user_a: User, user_b: User, user_c: User, role_a: Role): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = """ + USER BIG_BROTHER + ROLE NONE + Generator G, current value: 0, initial value: 1, increment: 1 + NEW_GEN -111 + USER BILL_JUNIOR + ROLE STOCKMGR + Generator G, current value: -111, initial value: 1, increment: 1 + NEW_GEN -333 + USER BILL_JUNIOR + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + -Effective user is BILL_JUNIOR + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + -Effective user is BILL_JUNIOR + USER MAVERICK + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + -Effective user is MAVERICK + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + -Effective user is MAVERICK + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3b1100a9be6769ab4c3bbad9eb6aff9143d694b5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 17:04:47 +0300 Subject: [PATCH 0500/1064] Added/Updated tests\bugs\core_4839_test.py: Added substitutions in order to suppress excessive lines produced by 'SHOW GRANTS': they may remain after some failed test teardown phases. --- tests/bugs/core_4839_test.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_4839_test.py b/tests/bugs/core_4839_test.py index 43a0299c..7b0109b9 100644 --- a/tests/bugs/core_4839_test.py +++ b/tests/bugs/core_4839_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4839 FBTEST: bugs.core_4839 +NOTES: + [15.05.2025] pzotov + Added substitutions in order to suppress excessive lines produced by 'SHOW GRANTS': + they may remain after some failed test teardown phases. """ import pytest @@ -28,17 +32,18 @@ commit; """ -act = isql_act('db', test_script) +substitutions = [('^((?!USAGE ON (SEQUENCE|EXCEPTION)).)*$', '')] -expected_stdout = """ - /* Grant permissions for this database */ - GRANT USAGE ON SEQUENCE GEN_BAR TO USER TMP$C4839 - GRANT USAGE ON EXCEPTION EXC_FOO TO USER TMP$C4839 -""" +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3.0') def test_1(act: Action, test_user: User): - act.expected_stdout = expected_stdout - act.execute() + expected_out = """ + GRANT USAGE ON SEQUENCE GEN_BAR TO USER TMP$C4839 + GRANT USAGE ON EXCEPTION EXC_FOO TO USER TMP$C4839 + """ + + act.expected_stdout = expected_out + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 96a5749848da1fb479bd4edc04b4b87276cf7419 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 18:37:06 +0300 Subject: [PATCH 0501/1064] Added/Updated tests\bugs\core_4468_test.py: Removed 'show grants' because its output very 'fragile' and can often change in master branch. It is enough to use custom VIEW ('v_users') to check data. --- tests/bugs/core_4468_test.py | 302 +++++++++++++---------------------- 1 file changed, 114 insertions(+), 188 deletions(-) diff --git a/tests/bugs/core_4468_test.py b/tests/bugs/core_4468_test.py index af1f7676..0c8974b3 100644 --- a/tests/bugs/core_4468_test.py +++ b/tests/bugs/core_4468_test.py @@ -14,8 +14,8 @@ Checked on 6.0.0.660; 5.0.3.1624; 4.0.6.3189; 3.0.13.33798 [15.05.2025] pzotov - Splitted output for versions up to 5.x and 6.x+: privilege "GRANT CREATE DATABASE TO USER ..." has appeared - in the output since 6.0.0.778 2025.05.07 d735e65a. + Removed 'show grants' because its output very 'fragile' and can often change in master branch. + It is enough to use custom VIEW ('v_users') to check data. """ import locale @@ -29,8 +29,8 @@ db = db_factory() -tmp_senior = user_factory('db', name='ozzy_osbourne', password='123', admin=True) -tmp_junior = user_factory('db', name='bon_scott', password='456') +tmp_senior = user_factory('db', name='tmp_4468_senior', password='123', admin=True) +tmp_junior = user_factory('db', name='tmp_4468_junior', password='456') act = isql_act('db', substitutions=substitutions) @@ -51,10 +51,20 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): -- 'delete record error' = for Srp -- This is minor bug in Legacy_UserManager but it will be remain 'as is', see letter from Alex 03-jun-2015 19:51. recreate view v_users as - select current_user who_am_i, current_role whats_my_role, u.sec$user_name non_sysdba_user_name, u.sec$admin non_sysdba_has_admin_role + select + current_user who_am_i + ,current_role whats_my_role + ,u.sec$user_name user_name + ,u.sec$admin sec_admin + ,g.rdb$privilege is not null as rdb_admin + ,g.rdb$grant_option rdb_adm_grant_option from rdb$database - left join sec$users u on u.sec$user_name in ( upper('{tmp_senior.name}'), upper('{tmp_junior.name}') ); + left join sec$users u on u.sec$user_name in ( upper('{tmp_senior.name}'), upper('{tmp_junior.name}') ) + left join rdb$user_privileges g on u.sec$user_name = g.rdb$user and g.rdb$privilege = upper('m') and g.rdb$relation_name = upper('rdb$admin') + order by user_name + ; commit; + grant select on v_users to public; commit; @@ -86,26 +96,24 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): alter user {tmp_junior.name} grant admin role; commit; - show grants; - + select 'point-3' msg, v.* from v_users v; grant rdb$admin to {tmp_junior.name}; commit; - show grants; + select 'point-4' msg, v.* from v_users v; alter user {tmp_junior.name} revoke admin role; commit; - select 'point-4' msg, v.* from v_users v; + select 'point-5' msg, v.* from v_users v; commit; revoke rdb$admin from {tmp_junior.name}; commit; - show grants; - select 'point-5' msg, v.* from v_users v; + select 'point-6' msg, v.* from v_users v; commit; -- User removes admin role from himself: @@ -122,9 +130,7 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): alter user {tmp_senior.name} revoke admin role; commit; - show grants; - - select 'point-6' msg, v.* from v_users v; + select 'point-7' msg, v.* from v_users v; commit; -- And after previous action he can not drop himself because now he is NOT member of admin role: @@ -134,232 +140,152 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): drop user {tmp_senior.name}; commit; - select 'point-7' msg, v.* from v_users v; + select 'point-8' msg, v.* from v_users v; commit; -- Trying reconnect with role RDB$ADMIN: connect '{act.db.dsn}' user '{tmp_senior.name}' password '{tmp_senior.password}' role 'RDB$ADMIN'; commit; - select 'point-8' msg, v.* from v_users v; - commit; - - show grants; + select 'finish' msg, v.* from v_users v; commit; """ - expected_5x = """ + expected_out = f""" MSG start - WHO_AM_I SYSDBA + WHO_AM_I {act.db.user} WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION MSG start - WHO_AM_I SYSDBA + WHO_AM_I {act.db.user} WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION Records affected: 2 MSG point-1 - WHO_AM_I SYSDBA + WHO_AM_I {act.db.user} WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION MSG point-1 - WHO_AM_I SYSDBA + WHO_AM_I {act.db.user} WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 MSG point-2 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION MSG point-2 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE MSG point-3 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION MSG point-3 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO BON_SCOTT GRANTED BY OZZY_OSBOURNE - GRANT RDB$ADMIN TO OZZY_OSBOURNE MSG point-4 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 MSG point-4 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE MSG point-5 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 MSG point-5 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE MSG point-6 - WHO_AM_I OZZY_OSBOURNE + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 1 - Statement failed, SQLSTATE = 28000 - delete record - -no permission for DELETE access to TABLE PLG - MSG point-7 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 1 - MSG point-8 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 1 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE - """ - - expected_6x = """ - MSG start - WHO_AM_I SYSDBA - WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG start - WHO_AM_I SYSDBA - WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 2 - MSG point-1 - WHO_AM_I SYSDBA - WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG point-1 - WHO_AM_I SYSDBA - WHATS_MY_ROLE NONE - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 2 - MSG point-2 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG point-2 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE - MSG point-3 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG point-3 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO BON_SCOTT GRANTED BY OZZY_OSBOURNE - GRANT RDB$ADMIN TO OZZY_OSBOURNE - MSG point-4 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG point-4 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE - Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE - MSG point-5 - WHO_AM_I OZZY_OSBOURNE - WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE - MSG point-5 - WHO_AM_I OZZY_OSBOURNE + USER_NAME {tmp_junior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION + MSG point-6 + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME BON_SCOTT - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 2 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE - MSG point-6 - WHO_AM_I OZZY_OSBOURNE + MSG point-7 + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 1 Statement failed, SQLSTATE = 28000 delete record -no permission for DELETE access to TABLE PLG - MSG point-7 - WHO_AM_I OZZY_OSBOURNE + MSG point-8 + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 1 - MSG point-8 - WHO_AM_I OZZY_OSBOURNE + MSG finish + WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN - NON_SYSDBA_USER_NAME OZZY_OSBOURNE - NON_SYSDBA_HAS_ADMIN_ROLE + USER_NAME {tmp_senior.name} + SEC_ADMIN + RDB_ADMIN + RDB_ADM_GRANT_OPTION 0 Records affected: 1 - /* Grant permissions for this database */ - GRANT SELECT ON V_USERS TO PUBLIC - GRANT RDB$ADMIN TO OZZY_OSBOURNE """ - act.expected_stdout = expected_5x if act.is_version('<6') else expected_6x + act.expected_stdout = expected_out # expected_5x if act.is_version('<6') else expected_6x act.isql(switches = ['-q'], input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From cbf1b41fb21961c9cb7620d9d82dca04362a69a4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 18:54:45 +0300 Subject: [PATCH 0502/1064] Added/Updated tests\bugs\gh_6910_test.py: Splitted expected_out for versions up to 5.x and 6.x+ (they become differ since 6.0.0.776). --- tests/bugs/gh_6910_test.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_6910_test.py b/tests/bugs/gh_6910_test.py index 9bfbbab6..7c3ecaa8 100644 --- a/tests/bugs/gh_6910_test.py +++ b/tests/bugs/gh_6910_test.py @@ -14,6 +14,10 @@ * state of 'set exec_path_display blr' command will not change after reconnect. ( https://github.com/FirebirdSQL/firebird/commit/32c3cf573bf36f576b6116983786107df5a2cb33 ) FBTEST: bugs.gh_6910 +NOTES: + [15.05.2025] pzotov + Splitted expected_out for versions up to 5.x and 6.x+ (they become differ since 6.0.0.776). + Checked on 6.0.0.778 """ import pytest @@ -39,9 +43,9 @@ end^ """ -act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) +act = isql_act('db', test_script) # , substitutions=[('[ \t]+', ' ')]) -expected_stdout = """ +expected_5x = """ Execution path (BLR): 0 blr_version5, 1 blr_begin, @@ -82,8 +86,31 @@ 30 blr_eoc """ +expected_6x = """ + Execution path (BLR): + 0 blr_version5, + 1 blr_begin, + 2 blr_begin, + 3 blr_label, 0, + 5 blr_begin, + 6 blr_end, + 7 blr_end, + 8 blr_end, + 9 blr_eoc + Execution path (BLR): + 0 blr_version5, + 1 blr_begin, + 2 blr_begin, + 3 blr_label, 0, + 5 blr_begin, + 6 blr_end, + 7 blr_end, + 8 blr_end, + 9 blr_eoc +""" + @pytest.mark.version('>=4.0.1') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_5x if act.is_version('<6') else expected_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From f01d94cef875d6518d66a192649376bce1fd1b12 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 19:07:53 +0300 Subject: [PATCH 0503/1064] Added/Updated tests\bugs\gh_7506_test.py: Additional subs for suppress excessive lines from 'show grants' output: remain only rows that contain prefix 'TMP_GH_7506_'. Replaced expected-out text: use f-syntax with reference to user/role names provided by action instance instead of hardcoding them. Checked on 6.0.0.778; 5.0.3.1649. Initial check was 24-apr-2023 on 5.0.0.1030. --- tests/bugs/gh_7506_test.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/bugs/gh_7506_test.py b/tests/bugs/gh_7506_test.py index b33fd999..44935dcd 100644 --- a/tests/bugs/gh_7506_test.py +++ b/tests/bugs/gh_7506_test.py @@ -9,20 +9,23 @@ 2) user; 1) role. NOTES: - Checked on 5.0.0.1030. + [15.05.2025] pzotov + Additional subs for suppress excessive lines from 'show grants' output: remain only rows that contain prefix 'TMP_GH_7506_'. + Replaced expected-out text: use f-syntax with reference to user/role names provided by action instance instead of hardcoding them. + Checked on 6.0.0.778; 5.0.3.1649. Initial check was 24-apr-2023 on 5.0.0.1030. """ import pytest from firebird.qa import * -tmp_user_boss = user_factory('db', name='tmp$gh_7506_john', password='123', plugin = 'Srp') -tmp_user_mngr = user_factory('db', name='tmp$gh_7506_mike', password='456', plugin = 'Srp') +tmp_user_boss = user_factory('db', name='tmp_gh_7506_john', password='123', plugin = 'Srp') +tmp_user_mngr = user_factory('db', name='tmp_gh_7506_mike', password='456', plugin = 'Srp') -tmp_role_boss = role_factory('db', name='tmp$gh_7506_boss') -tmp_role_mngr = role_factory('db', name='tmp$gh_7506_mngr') +tmp_role_boss = role_factory('db', name='tmp_gh_7506_boss') +tmp_role_mngr = role_factory('db', name='tmp_gh_7506_mngr') db = db_factory() -act = python_act('db', substitutions=[('[ \t]+', ' ')]) +act = python_act('db', substitutions = [ ('[ \t]+', ' '), ('^((?!TMP_GH_7506_).)*$', '') ] ) @pytest.mark.version('>=5.0') def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: Role, tmp_role_mngr: Role, capsys): @@ -50,13 +53,11 @@ def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: """ act.expected_stdout = f""" - /* Grant permissions for this database */ GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON TEST TO USER {tmp_user_boss.name.upper()} GRANT SELECT, UPDATE (F04, F05, F06) ON TEST TO USER {tmp_user_boss.name.upper()} WITH GRANT OPTION GRANT SELECT ON TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} GRANT UPDATE (F01, F03) ON TEST TO USER {tmp_user_mngr.name.upper()} GRANT UPDATE (F04, F05, F06) ON TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} - GRANT ALL ON TEST TO VIEW V_TEST """ act.isql(input = test_user_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout @@ -90,13 +91,12 @@ def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: """ act.expected_stdout = f""" - /* Grant permissions for this database */ - GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON TEST TO ROLE TMP$GH_7506_BOSS - GRANT SELECT, UPDATE (F04, F05, F06) ON TEST TO ROLE TMP$GH_7506_BOSS WITH GRANT OPTION - GRANT SELECT ON TEST TO ROLE TMP$GH_7506_MNGR GRANTED BY TMP$GH_7506_JOHN - GRANT UPDATE (F01, F03) ON TEST TO ROLE TMP$GH_7506_MNGR - GRANT UPDATE (F04, F05, F06) ON TEST TO ROLE TMP$GH_7506_MNGR GRANTED BY TMP$GH_7506_JOHN - GRANT TMP$GH_7506_BOSS TO TMP$GH_7506_JOHN + GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON TEST TO ROLE {tmp_role_boss.name} + GRANT SELECT, UPDATE (F04, F05, F06) ON TEST TO ROLE {tmp_role_boss.name} WITH GRANT OPTION + GRANT SELECT ON TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} + GRANT UPDATE (F01, F03) ON TEST TO ROLE {tmp_role_mngr.name} + GRANT UPDATE (F04, F05, F06) ON TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} + GRANT {tmp_role_boss.name} TO {tmp_user_boss.name} """ act.isql(input = test_role_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 4de38396e113ee8183e84598304f4124f93bcc8d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 15 May 2025 23:52:35 +0300 Subject: [PATCH 0504/1064] Added/Updated tests\bugs\core_4831_test.py: Removed 'show grants', use query to rdb$ tables instead. --- tests/bugs/core_4831_test.py | 58 +++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_4831_test.py b/tests/bugs/core_4831_test.py index bef272a0..ce66cfb9 100644 --- a/tests/bugs/core_4831_test.py +++ b/tests/bugs/core_4831_test.py @@ -14,29 +14,39 @@ db = db_factory() -role = role_factory('db', name='r_20150608_20h03m') - -test_script = """ - set wng off; - -- create role r_20150608_20h03m; - -- commit; - revoke all on all from role r_20150608_20h03m; -- this was failed, possibly due to: http://sourceforge.net/p/firebird/code/61729 - commit; - show grants; - -- commit; - -- drop role r_20150608_20h03m; - --commit; -""" - -act = isql_act('db', test_script) - -expected_stderr = """ -There is no privilege granted in this database -""" +tmp_role = role_factory('db', name='r_20150608_20h03m') +act = isql_act('db') @pytest.mark.version('>=3.0') -def test_1(act: Action, role: Role): - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stdout == act.clean_expected_stdout and - act.clean_stderr == act.clean_expected_stderr) +def test_1(act: Action, tmp_role: Role): + + test_sql = f""" + set list on; + set count on; + set wng off; + + -- this failed, possibly by: http://sourceforge.net/p/firebird/code/61729 + -- alexpeshkoff 2015-06-04 + -- Postfix for CORE-4821: fixed segfault in REVOKE ALL ON ALL + revoke all on all from role {tmp_role.name}; + + commit; + select + g.rdb$privilege + ,g.rdb$grant_option + ,g.rdb$relation_name + ,g.rdb$user + ,g.rdb$object_type + from rdb$user_privileges g + join sec$users u on g.rdb$user = u.sec$user_name + where g.rdb$user = '{tmp_role.name.upper()}' + ; + """ + + act.expected_stdout = """ + Records affected: 0 + """ + + act.isql(input = test_sql, combine_output = True) + + assert act.clean_stdout == act.clean_expected_stdout From dc47f45b1fbc4b8ccbb62d3cf7f15fbf9e4380d9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 16 May 2025 10:30:52 +0300 Subject: [PATCH 0505/1064] Added/Updated tests\functional\services\test_user_management.py: added assert and diagnostic messages --- .../services/test_user_management.py | 96 ++++++++++++------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/tests/functional/services/test_user_management.py b/tests/functional/services/test_user_management.py index 537d8084..9b4ad4bf 100644 --- a/tests/functional/services/test_user_management.py +++ b/tests/functional/services/test_user_management.py @@ -9,8 +9,8 @@ 2) Python firebird-driver functions (from class Server) NB. - User with name 'tmp$test$user$' must NOT present in security_db. - Correctness of adding user is verified by establishing TCP-based attachment to test DB using its login/password. + User with name 'tmp_vaclav$' must NOT present in security_db. + Results are verified by attempts to make TCP connection to the test DB using login/password of this user. See doc: https://firebird-driver.readthedocs.io/en/latest/usage-guide.html#user-maintenance @@ -18,77 +18,103 @@ https://firebird-driver.readthedocs.io/en/latest/ref-core.html#serveruserservices FBTEST: functional.services.user_management """ - +import sys import pytest from firebird.qa import * import firebird.driver -from firebird.driver import TPB, Isolation, core as fb_core +from firebird.driver import TPB, Isolation, core as fb_core, DatabaseError + +#sys.stdout.reconfigure(encoding='utf-8') db = db_factory(init = "create sequence g;") act = python_act('db') -test_expected_stdout = """ - POINT: 1 - SEC$USER_NAME: TMP$TEST$USER - SEC$FIRST_NAME: John - SEC$LAST_NAME: Smith - SEC$ADMIN: True - - POINT: 2 - SEC$USER_NAME: TMP$TEST$USER - SEC$FIRST_NAME: Robert - SEC$LAST_NAME: Jackson - SEC$ADMIN: False - - POINT: 3 - SEC$USER_NAME: None - SEC$FIRST_NAME: None - SEC$LAST_NAME: None - SEC$ADMIN: None -""" - @pytest.mark.version('>=3') def test_1(act: Action, capsys): #---------------------------------------------------------- - def print_user_data(con, cur, prepared_sttm): + def print_user_data(con, cur, prepared_sttm, mode, uname): con.commit() con.begin() - cur.execute(prepared_sttm, (TMP_USER_NAME,)) + cur.execute(prepared_sttm, (uname,)) col_hdr=cur.description for r in cur: for i in range(0,len(col_hdr)): print( (col_hdr[i][0] +':').ljust(32), r[i] ) + if mode != 'del': + if cur.affected_rows == 0: + cur.execute('select sec$user_name from sec$users') + existing_users = '\n'.join( [r[0].rstrip() for r in cur.fetchall()] ) + assert False, f"Problem with security.db for {mode=}: could not find expected record with sec$user_name = '{uname}' using charset = {con.charset}, {existing_users=}" + else: + assert cur.affected_rows == 0, f"Problem with security.db for {mode=}: UNEXPECTED record encountered with sec$user_name = '{uname}', {cur.affected_rows=}" + #---------------------------------------------------------- - TMP_USER_NAME = 'tmp$test$user'.upper() - sttm = 'select gen_id(g,1) as point, sec$user_name, sec$first_name, sec$last_name, sec$admin from rdb$database left join sec$users on sec$user_name = ?' + TMP_USER_NAME = 'tmp_vaclav'.upper() + + # ::: NOTE ::: + # > spb.insert_string(SrvUserOption.USER_NAME, user_name, encoding=self._srv().encoding) + # self.vtable.insertString(self, self.status, tag, value.encode(encoding, errors)) + # UnicodeEncodeError: 'ascii' codec can't encode character '\xe1' in position 5: ordinal not in range(128) + #TMP_USER_NAME = '"tmp_Václav"' + + sttm = 'select gen_id(g,1) as point, sec$user_name, sec$first_name, sec$last_name, sec$admin from rdb$database join sec$users on sec$user_name = ?' - with act.db.connect() as con: + with act.db.connect(charset = 'utf8') as con: con.begin() cur = con.cursor() + prepared_sttm = cur.prepare(sttm) with act.connect_server() as srv: svc = fb_core.ServerUserServices(srv) + + # not helped for non-ascii user name: + svc._srv().encoding = con.charset + # print(svc._srv().encoding) + if svc.exists(user_name = TMP_USER_NAME): svc.delete(user_name = TMP_USER_NAME) svc.add( user_name = TMP_USER_NAME, password = '123', first_name = 'John', last_name = 'Smith', admin = True) - print_user_data(con, cur, prepared_sttm) + print_user_data(con, cur, prepared_sttm, 'add', TMP_USER_NAME) # Here we make sure that user actually exists and can make connecttion: - with act.db.connect(user = TMP_USER_NAME, password = '123') as con_check: + with act.db.connect(user = TMP_USER_NAME, password = '123', charset = con.charset) as con_check: pass svc.update( user_name = TMP_USER_NAME, last_name = 'Jackson', admin = False, first_name = 'Robert') - print_user_data(con, cur, prepared_sttm) + print_user_data(con, cur, prepared_sttm, 'upd', TMP_USER_NAME) svc.delete(user_name = TMP_USER_NAME) - print_user_data(con, cur, prepared_sttm) - - act.expected_stdout = test_expected_stdout + print_user_data(con, cur, prepared_sttm, 'del', TMP_USER_NAME) + try: + with act.db.connect(user = TMP_USER_NAME, password = '123') as con_check: + print('UNEXPECTED: user must not exist at this point!') + except DatabaseError as e: + # 335544472 ==> Your user name and password are not defined ... + for x in e.gds_codes: + print(x) + + expected_out = f""" + POINT: 1 + SEC$USER_NAME: {TMP_USER_NAME} + SEC$FIRST_NAME: John + SEC$LAST_NAME: Smith + SEC$ADMIN: True + + POINT: 2 + SEC$USER_NAME: {TMP_USER_NAME} + SEC$FIRST_NAME: Robert + SEC$LAST_NAME: Jackson + SEC$ADMIN: False + + 335544472 + """ + + act.expected_stdout = expected_out act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From be26d0e78600296cf85ddbbca408003ea43ed02a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 16 May 2025 10:33:25 +0300 Subject: [PATCH 0506/1064] Added/Updated tests\functional\services\test_user_management.py: fixed typo. --- tests/functional/services/test_user_management.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/services/test_user_management.py b/tests/functional/services/test_user_management.py index 9b4ad4bf..df67e4b7 100644 --- a/tests/functional/services/test_user_management.py +++ b/tests/functional/services/test_user_management.py @@ -9,7 +9,7 @@ 2) Python firebird-driver functions (from class Server) NB. - User with name 'tmp_vaclav$' must NOT present in security_db. + User with name 'tmp_vaclav' must NOT present in security_db. Results are verified by attempts to make TCP connection to the test DB using login/password of this user. See doc: From 77274449bc9cec6e44b5fbb646ef46151e785efb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 17 May 2025 10:35:56 +0300 Subject: [PATCH 0507/1064] Added/Updated tests\functional\gtcs\test_minimum_grant_test.py: replaced hard-coded user names with values provided by user_factory. --- .../gtcs/test_minimum_grant_test.py | 111 +++++++----------- 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/tests/functional/gtcs/test_minimum_grant_test.py b/tests/functional/gtcs/test_minimum_grant_test.py index 6dd780e5..29a53c51 100644 --- a/tests/functional/gtcs/test_minimum_grant_test.py +++ b/tests/functional/gtcs/test_minimum_grant_test.py @@ -19,72 +19,51 @@ db = db_factory() -test_script = """ - set list on; +tmp_user1 = user_factory('db', name='tmp_gtcs_34_a', password='123') +tmp_user2 = user_factory('db', name='tmp_gtcs_34_b', password='456') - set term ^; - execute block as - begin - begin - execute statement 'drop user tmp$qa_user1' with autonomous transaction; - when any do begin end - end - - begin - execute statement 'drop user tmp$qa_user2' with autonomous transaction; - when any do begin end - end - - end^ - set term ;^ - commit; - - create user tmp$qa_user1 password '123'; - create user tmp$qa_user2 password '456'; - commit; - - create table test (c1 int); - commit; - - grant insert on test to tmp$qa_user1; - grant select on test to tmp$qa_user2; - commit; - - ------------------------------------------------- - connect '$(DSN)' user tmp$qa_user1 password '123'; - select current_user as whoami from rdb$database; - insert into test values(1); -- should pass - select * from test; -- should fail - commit; - - ------------------------------------------------- - connect '$(DSN)' user tmp$qa_user2 password '456'; - select current_user as whoami from rdb$database; - insert into test values(2); -- should fail - select * from test; -- should pass - commit; -""" - -act = isql_act('db', test_script, substitutions=substitutions) - -expected_stdout = """ - WHOAMI TMP$QA_USER1 - WHOAMI TMP$QA_USER2 - C1 1 -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - no permission for read/select access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - no permission for insert/write access to TABLE TEST -""" +act = python_act('db', substitutions = substitutions) @pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) +def test_1(act: Action, tmp_user1: User, tmp_user2: User): + + test_sql = f""" + set list on; + + create table test (f01 int); + commit; + + grant insert on test to {tmp_user1.name}; + grant select on test to {tmp_user2.name}; + commit; + + ------------------------------------------------- + connect '{act.db.dsn}' user {tmp_user1.name} password '{tmp_user1.password}'; + select current_user as whoami from rdb$database; + insert into test values(1); -- should pass + select * from test; -- should fail + commit; + + ------------------------------------------------- + connect '{act.db.dsn}' user {tmp_user2.name} password '{tmp_user2.password}'; + select current_user as whoami from rdb$database; + insert into test values(2); -- should fail + select * from test; -- should pass + commit; + """ + + act.expected_stdout = f""" + WHOAMI {tmp_user1.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for read access + + WHOAMI {tmp_user2.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for write access + + F01 1 + """ + act.isql(input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 15fd7d45cded093eb302c79c977944950f8480db Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 18 May 2025 13:35:05 +0300 Subject: [PATCH 0508/1064] Added/Updated tests\bugs\gh_7989_test.py: Checked on 6.0.0.269; 6.0.0.273; 6.0.0.783. See notes. --- tests/bugs/gh_7989_test.py | 152 +++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 tests/bugs/gh_7989_test.py diff --git a/tests/bugs/gh_7989_test.py b/tests/bugs/gh_7989_test.py new file mode 100644 index 00000000..59b7d9c0 --- /dev/null +++ b/tests/bugs/gh_7989_test.py @@ -0,0 +1,152 @@ +#coding:utf-8 + +""" +ID: issue-7989 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7989 +TITLE: Improve performance of external (UDR) functions +DESCRIPTION: + We can estimate perfomance by comparison of time that is spent to call UDR vs result of some crypt function. + Function crypt_hash( using SHA512) has been selected for that because of notable CPU consumation. + Stored procedured SP_GEN_HASH is created for evaluation of crypt hash, it will run loop for N_HASH_EVALUATE_COUNT times. + Duration for each measure is difference between psutil.Process(fb_pid).cpu_times() counters. + + We do to call SP vs UDR, with adding results to map. + UDR that determines whether date relates to LEAP year is used for this test. + It is defined as 'udf_compat!UC_isLeapYear' in UDR engine, see $FB_HOME/upgrade/v4.0/udf_replace.sql + + Finally, we get ratio between medians of these measures (see 'median_ratio') + Test is considered as passed if median_ratio less than threshold . +NOTES: + [18.05.2025] pzotov. + Initial commit that introduces inmprovement: 29.02.2024 00:43 + https://github.com/FirebirdSQL/firebird/commit/547cb8388b9c72a329ed9bfe8c25f8ee696a112e + Postfix for #7989 - Improve performance of external (UDR) functions: 17.03.2024 04:14 + https://github.com/FirebirdSQL/firebird/commit/e4377213b4c9767cafe92502797db4f040a9e6be + + 1. Medians ratio on Windows: + * before: 0.46 + * after: 0.31 + 2. Test DB must NOT have charset = utf8, otherwise 'implementation limit exceeded' will raise; 'ascii' charset was selected for work. + 3. Just for info: isLeapYear() can be implemented using pure PSQL: + create or alter function isLeapPSQL (a_year int) returns boolean as + begin + return bin_and( (a_year * 1073750999), 3221352463) <= 126976; + end + Benchmark shows that this code *was* faster than UDR before #547cb838 but now it runs slower (with raio ~ 2450/3050 ms). + See: + [EN]: https://hueffner.de/falk/blog/a-leap-year-check-in-three-instructions.html + [RU]: https://habr.com/ru/articles/910188/ + + Checked on 6.0.0.269; 6.0.0.273; 6.0.0.783. +""" +import os +import psutil +import pytest +from firebird.qa import * + +#-------------------------------------------------------------------- +def median(lst): + n = len(lst) + s = sorted(lst) + return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None +#-------------------------------------------------------------------- + +########################### +### S E T T I N G S ### +########################### + +# How many times we do measure: +N_MEASURES = 21 + +N_UDR_CALLS_COUNT = 50000 + +# How many iterations must be done for hash evaluation: +N_HASH_EVALUATE_COUNT = 3000 + +# Maximal value for ratio between maximal and minimal medians +# +################ +MAX_RATIO = 0.40 +################ + +init_script = \ +f''' + set term ^; + create or alter procedure sp_gen_hash (n_cnt int) as + declare v_hash varbinary(64); + declare s varchar(32765); + begin + s = lpad('', 32765, uuid_to_char(gen_uuid())); + while (n_cnt > 0) do + begin + v_hash = crypt_hash(s using SHA512); + n_cnt = n_cnt - 1; + end + end + ^ + + -- from $FB_HOME/upgrade/v4.0/udf_replace.sql: + create or alter function isLeapUDR (a_timestamp timestamp) returns boolean + external name 'udf_compat!UC_isLeapYear' + engine udr; + ^ + create or alter procedure sp_udr_call (n_cnt int) as + declare a_date date; + declare b boolean; + begin + a_date = current_date; + while (n_cnt > 0) do + begin + b = isLeapUDR(a_date); + n_cnt = n_cnt - 1; + end + end + ^ + commit + ^ +''' + +db = db_factory(init = init_script, charset = 'ascii') +act = python_act('db') + +expected_stdout = """ + Medians ratio: acceptable +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + with act.db.connect() as con: + cur=con.cursor() + cur.execute('select mon$server_pid as p from mon$attachments where mon$attachment_id = current_connection') + fb_pid = int(cur.fetchone()[0]) + + times_map = {} + for i in range(0, N_MEASURES): + fb_info_init = psutil.Process(fb_pid).cpu_times() + cur.callproc( 'sp_gen_hash', (N_HASH_EVALUATE_COUNT,) ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + times_map[ 'hash_eval', i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + fb_info_init = psutil.Process(fb_pid).cpu_times() + cur.callproc( 'sp_udr_call', (N_UDR_CALLS_COUNT,) ) + fb_info_curr = psutil.Process(fb_pid).cpu_times() + times_map[ 'udr_call', i ] = max(fb_info_curr.user - fb_info_init.user, 0.000001) + + + sp_gen_hash_median = median([v for k,v in times_map.items() if k[0] == 'hash_eval']) + sp_udr_call_median = median([v for k,v in times_map.items() if k[0] == 'udr_call']) + + median_ratio = sp_udr_call_median / sp_gen_hash_median + + print( 'Medians ratio: ' + ('acceptable' if median_ratio <= MAX_RATIO else '/* perf_issue_tag */ POOR: %s, more than threshold: %s' % ( '{:9g}'.format(median_ratio), '{:9g}'.format(MAX_RATIO) ) ) ) + if median_ratio > MAX_RATIO: + print(f'CPU times for each of {N_MEASURES} measures:') + for sp_name in ('hash_eval', 'udr_call', ): + print(f'{sp_name=}:') + for p in [v for k,v in times_map.items() if k[0] == sp_name]: + print(p) + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 7a2fb15bcaf7b13bd79406bea262da52ef6fee98 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 20 May 2025 20:27:25 +0300 Subject: [PATCH 0509/1064] Added/Updated tests\bugs\gh_8194_test.py: Added temporary mark 'disabled_in_forks' to SKIP this test when QA runs agains *fork* of standard FB --- tests/bugs/gh_8194_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/bugs/gh_8194_test.py b/tests/bugs/gh_8194_test.py index 3f51ad6b..bf208584 100644 --- a/tests/bugs/gh_8194_test.py +++ b/tests/bugs/gh_8194_test.py @@ -28,6 +28,9 @@ Confirmed bug on 5.0.3.1648-ca2f3e7, got: internal Firebird consistency check (page in use during flush (210), file: cch.cpp line: 2828) Checked on 5.0.3.1649-afcfa1a (intermediate snapshot) - all OK. Reduced min_version to 5.0.3. + + [20.05.2024] pzotov + Added temporary mark 'disabled_in_forks' to SKIP this test when QA runs agains *fork* of standard FB. """ import re @@ -44,6 +47,7 @@ db = db_factory() act = python_act('db') +@pytest.mark.disabled_in_forks @pytest.mark.version('>=5.0.3') def test_1(act: Action, capsys): From 0a47c9d9c3413f7c0681aca3ec2517228576f969 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 24 May 2025 23:19:15 +0300 Subject: [PATCH 0510/1064] Added/Updated tests\bugs\core_5973_test.py: Splitted expected* variables for versions up to 5.x and 6.x+. This is needed after 11d5d5 ('Fix for #8082 ... user buffers directly (#8145)') by Dmitry Sibiryakov. --- tests/bugs/core_5973_test.py | 47 +++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_5973_test.py b/tests/bugs/core_5973_test.py index 844e4be5..f6e93530 100644 --- a/tests/bugs/core_5973_test.py +++ b/tests/bugs/core_5973_test.py @@ -9,7 +9,11 @@ [05.03.2021] added subst.: max. floating point precision on Linux is 15 rather than on Windows (16 digits). JIRA: CORE-5973 -FBTEST: bugs.core_5973 +NOTES: + [24.05.2025] pzotov + Splitted expected* variables for versions up to 5.x and 6.x+ + This is needed after 11d5d5 ("Fix for #8082 ... user buffers directly (#8145)") by Dmitry Sibiryakov. + Discussed in email 24.05.2025 22:06, subj: "one more consequence of 11d5d5 ..." (since 15.05.2025 17:25). """ import pytest @@ -66,14 +70,7 @@ act = isql_act('db', test_script, substitutions=[('0.0000000000000000', '0.000000000000000')]) -expected_stdout = """ - GREATEST_DF34_FOR_POS_SCOPE Infinity - GREATEST_DF34_FOR_NEG_SCOPE -Infinity - APPROX_ZERO_DF34_FOR_POS_SCOPE 0.0000000000000000 - APPROX_ZERO_DF34_FOR_NEG_SCOPE 0.0000000000000000 -""" - -expected_stderr = """ +expected_out_5x = """ Statement failed, SQLSTATE = 22003 Dynamic SQL Error -SQL error code = -303 @@ -93,12 +90,34 @@ Dynamic SQL Error -SQL error code = -303 -Floating-point underflow. The exponent of a floating-point operation is less than the magnitude allowed. + + GREATEST_DF34_FOR_POS_SCOPE Infinity + GREATEST_DF34_FOR_NEG_SCOPE -Infinity + APPROX_ZERO_DF34_FOR_POS_SCOPE 0.000000000000000 + APPROX_ZERO_DF34_FOR_NEG_SCOPE 0.000000000000000 +""" + +expected_out_6x = """ + Statement failed, SQLSTATE = 22003 + Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Floating-point underflow. The exponent of a floating-point operation is less than the magnitude allowed. + + Statement failed, SQLSTATE = 22003 + Floating-point underflow. The exponent of a floating-point operation is less than the magnitude allowed. + + GREATEST_DF34_FOR_POS_SCOPE Infinity + GREATEST_DF34_FOR_NEG_SCOPE -Infinity + APPROX_ZERO_DF34_FOR_POS_SCOPE 0.000000000000000 + APPROX_ZERO_DF34_FOR_NEG_SCOPE 0.000000000000000 """ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 722083d8abf4932905037b10898f09f915d83423 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 24 May 2025 23:28:38 +0300 Subject: [PATCH 0511/1064] Added/Updated tests\bugs\gh_6416_test.py: Splitted expected* variables for versions up to 5.x and 6.x+. This is needed after 11d5d5 ('Fix for #8082 ... user buffers directly (#8145)') by Dmitry Sibiryakov. --- tests/bugs/gh_6416_test.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_6416_test.py b/tests/bugs/gh_6416_test.py index 9b2ca65a..8fe8b864 100644 --- a/tests/bugs/gh_6416_test.py +++ b/tests/bugs/gh_6416_test.py @@ -8,7 +8,7 @@ Test creates table with columns belonging to "new datatypes" family: int128, decfloat and time[stamp] with time zone. Also, one record is added into this table with values which are valid for numeric types in FB 4.x+ (time zone fields can remain null or arbitrary). - This DB is them copied to another DB (using file-level call of shutil.copy2()). + Further, this DB is copied to another DB using file-level call of shutil.copy2(). Another DB filename must match to the specified in the databases.conf (alias defined by 'REQUIRED_ALIAS' variable). Its alias has special value for DataTypeCompatibility parameter. Connection to this DB and query to a table with 'new datatypes' must return SQLDA with *old* types which are known for FB versions prior 4.x. @@ -26,6 +26,11 @@ (for LINUX this equality is case-sensitive, even when aliases are compared!) Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142. + + [24.05.2025] pzotov + Splitted expected* variables for versions up to 5.x and 6.x+ + This is needed after 11d5d5 ("Fix for #8082 ... user buffers directly (#8145)") by Dmitry Sibiryakov. + Discussed in email 24.05.2025 22:06, subj: "one more consequence of 11d5d5 ..." (since 15.05.2025 17:25). """ import re @@ -100,7 +105,7 @@ def test_1(act: Action, capsys): from test; ''' - act.expected_stdout = f""" + expected_out_5x = f""" 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 @@ -114,6 +119,20 @@ def test_1(act: Action, capsys): -Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. """ + expected_out_6x = f""" + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 05: sqltype: 580 INT64 Nullable scale: 0 subtype: 1 len: 8 + 06: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + 07: sqltype: 560 TIME Nullable scale: 0 subtype: 0 len: 4 + 08: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 + Statement failed, SQLSTATE = 22003 + Floating-point overflow. The exponent of a floating-point operation is greater than the magnitude allowed. + """ + + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x act.isql(switches = ['-q'], input = test_sql, combine_output = True, credentials = False, connect_db = False) assert act.clean_stdout == act.clean_expected_stdout act.reset() From e3543c0322ee0a987caa64ee269b3987e674a503 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 27 May 2025 14:17:25 +0300 Subject: [PATCH 0512/1064] Added/Updated tests\bugs\gh_8524_test.py: ACHTUNG: see notes. Test normally must have '@pytest.mark.skip'. Comment out this marker if pytest will be run NOT from scheduler. --- tests/bugs/gh_8524_test.py | 307 +++++++++++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 tests/bugs/gh_8524_test.py diff --git a/tests/bugs/gh_8524_test.py b/tests/bugs/gh_8524_test.py new file mode 100644 index 00000000..f728d941 --- /dev/null +++ b/tests/bugs/gh_8524_test.py @@ -0,0 +1,307 @@ +#coding:utf-8 + +""" +ID: issue-8524 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8524 +TITLE: ISQL will truncate lines longer than 255 when pasting +DESCRIPTION: + Test creates temporary batch file with requirement to perform following commands: + ========== + chcp 65001 + {act.vars['isql']} -q + exit + ========== + This batch further is called as CHILD process via: 'cmd.exe /c start ' which will launch ISQL. + ISQL process will have console window (which will appear on screen) and we wioll try to paste some text in it. + + Text may contain non-printable / non-readable characters, so we have to check not the result of pasting but + value of CHAR_LENGTH(). This is done by creating a table and using INSERT command: + ========= + insert into test(s_utf8) values( + '{long_utf8_data}' + ) returning char_length(s_utf8); + ========= + Result of this command is redirected to log. + Finally, we open this log and parse it in order to see there: 'CHAR_LENGTH {checked_char_len}' + test can be considered as successful if we actually found this line. +NOTES: + [27.05.2025] pzotov + 0. Package 'pywin32' must be installed for this test (pip install pywin32). + 1. Test was added just to be able to check result of pasting long text in existing ISQL console. + This test will not able to create console window if python was launched by scheduler and + appropriate task has not set to: "Run only when user is logged on". + Because of that, this test has '@pytest.mark.skip' marker. + ################################################## + REMOVE OR COMMENT OUT THIS MARKER TO RUN THIS TEST + ################################################## + + 2. String that we want to be pasted into console must NOT have two adjacent characters, e.g. 'commit'. + Otherwise only first of them will be actually pasted but others will be 'swallowed' for unknown reason. + 3. Every line of (i.e. text to be pasted in console of ISQL) must be prefixed with TWO characters: ascii_char(13) and ascii_char(10). + It is NOT enough to use as prefix only CHR_10 at this case! + 4. Command processor ('cmd.exe') must change code page to 65001 before running ISQL, thus we launch BATCH rather than just ISQL (as child process). + + Checked on 6.0.0.789. +""" + +import os +import random +import win32gui +import win32con +import subprocess +import time +from pathlib import Path + +import pytest +from firebird.qa import * + +db = db_factory(charset = 'utf8') + +#----------------------------------------------------------- + +def get_random_unicode(length): + + # https://jrgraphix.net/r/Unicode/ + UNICODE_RANGES_MAP = { + (0x0028, 0x007E) : 'Basic Latin WITHOUT apostrophe and control character , 0x7F', + (0x00A0, 0x00FF) : 'Latin-1 Supplement', + (0x0100, 0x017F) : 'Latin Extended-A', + (0x0180, 0x024F) : 'Latin Extended-B', + (0x0400, 0x04FF) : 'Cyrillic', + (0x0500, 0x052F) : 'Cyrillic Supplementary', + (0x0300, 0x036F) : 'Combining Diacritical Marks', + (0x0250, 0x02AF) : 'IPA Extensions', + (0x0370, 0x03FF) : 'Greek and Coptic', + (0x0530, 0x058F) : 'Armenian', + (0x02B0, 0x02FF) : 'Spacing Modifier Letters', + (0x0590, 0x05FF) : 'Hebrew', + (0x0600, 0x06FF) : 'Arabic', + (0x0700, 0x074F) : 'Syriac', + (0x0780, 0x07BF) : 'Thaana', + (0x0900, 0x097F) : 'Devanagari', + (0x0980, 0x09FF) : 'Bengali', + (0x0A00, 0x0A7F) : 'Gurmukhi', + (0x0A80, 0x0AFF) : 'Gujarati', + (0x0B00, 0x0B7F) : 'Oriya', + (0x0B80, 0x0BFF) : 'Tamil', + (0x0C00, 0x0C7F) : 'Telugu', + (0x0C80, 0x0CFF) : 'Kannada', + (0x0D00, 0x0D7F) : 'Malayalam', + (0x0D80, 0x0DFF) : 'Sinhala', + (0x0E00, 0x0E7F) : 'Thai', + (0x0E80, 0x0EFF) : 'Lao', + (0x0F00, 0x0FFF) : 'Tibetan', + (0x1000, 0x109F) : 'Myanmar', + (0x10A0, 0x10FF) : 'Georgian', + (0x1100, 0x11FF) : 'Hangul Jamo', + (0x1200, 0x137F) : 'Ethiopic', + (0x13A0, 0x13FF) : 'Cherokee', + (0x1400, 0x167F) : 'Unified Canadian Aboriginal Syllabics', + (0x1680, 0x169F) : 'Ogham', + (0x16A0, 0x16FF) : 'Runic', + (0x1700, 0x171F) : 'Tagalog', + (0x1720, 0x173F) : 'Hanunoo', + (0x1740, 0x175F) : 'Buhid', + (0x1760, 0x177F) : 'Tagbanwa', + (0x1780, 0x17FF) : 'Khmer', + (0x1800, 0x18AF) : 'Mongolian', + (0x1900, 0x194F) : 'Limbu', + (0x1950, 0x197F) : 'Tai Le', + (0x19E0, 0x19FF) : 'Khmer Symbols', + (0x1D00, 0x1D7F) : 'Phonetic Extensions', + (0x1E00, 0x1EFF) : 'Latin Extended Additional', + (0x1F00, 0x1FFF) : 'Greek Extended', + (0x2000, 0x206F) : 'General Punctuation', + (0x2070, 0x209F) : 'Superscripts and Subscripts', + (0x20A0, 0x20CF) : 'Currency Symbols', + (0x20D0, 0x20FF) : 'Combining Diacritical Marks for Symbols', + (0x2100, 0x214F) : 'Letterlike Symbols', + (0x2150, 0x218F) : 'Number Forms', + (0x2190, 0x21FF) : 'Arrows', + (0x2200, 0x22FF) : 'Mathematical Operators', + (0x2300, 0x23FF) : 'Miscellaneous Technical', + (0x2400, 0x243F) : 'Control Pictures', + (0x2440, 0x245F) : 'Optical Character Recognition', + (0x2460, 0x24FF) : 'Enclosed Alphanumerics', + (0x2500, 0x257F) : 'Box Drawing', + (0x2580, 0x259F) : 'Block Elements', + (0x25A0, 0x25FF) : 'Geometric Shapes', + (0x2600, 0x26FF) : 'Miscellaneous Symbols', + (0x2700, 0x27BF) : 'Dingbats', + (0x27C0, 0x27EF) : 'Miscellaneous Mathematical Symbols-A', + (0x27F0, 0x27FF) : 'Supplemental Arrows-A', + (0x2800, 0x28FF) : 'Braille Patterns', + (0x2900, 0x297F) : 'Supplemental Arrows-B', + (0x2980, 0x29FF) : 'Miscellaneous Mathematical Symbols-B', + (0x2A00, 0x2AFF) : 'Supplemental Mathematical Operators', + (0x2B00, 0x2BFF) : 'Miscellaneous Symbols and Arrows', + (0x2E80, 0x2EFF) : 'CJK Radicals Supplement', + (0x2F00, 0x2FDF) : 'Kangxi Radicals', + (0x2FF0, 0x2FFF) : 'Ideographic Description Characters', + (0x3000, 0x303F) : 'CJK Symbols and Punctuation', + (0x3040, 0x309F) : 'Hiragana', + (0x30A0, 0x30FF) : 'Katakana', + (0x3100, 0x312F) : 'Bopomofo', + (0x3130, 0x318F) : 'Hangul Compatibility Jamo', + (0x3190, 0x319F) : 'Kanbun', + (0x31A0, 0x31BF) : 'Bopomofo Extended', + (0x31F0, 0x31FF) : 'Katakana Phonetic Extensions', + (0x3200, 0x32FF) : 'Enclosed CJK Letters and Months', + (0x3300, 0x33FF) : 'CJK Compatibility', + (0x3400, 0x4DBF) : 'CJK Unified Ideographs Extension A', + (0x4DC0, 0x4DFF) : 'Yijing Hexagram Symbols', + (0x4E00, 0x9FFF) : 'CJK Unified Ideographs', + (0xA000, 0xA48F) : 'Yi Syllables', + (0xA490, 0xA4CF) : 'Yi Radicals', + (0xAC00, 0xD7AF) : 'Hangul Syllables', + (0xE000, 0xF8FF) : 'Private Use Area', + (0xF900, 0xFAFF) : 'CJK Compatibility Ideographs', + (0xFB00, 0xFB4F) : 'Alphabetic Presentation Forms', + (0xFB50, 0xFDFF) : 'Arabic Presentation Forms-A', + (0xFE00, 0xFE0F) : 'Variation Selectors', + (0xFE20, 0xFE2F) : 'Combining Half Marks', + (0xFE30, 0xFE4F) : 'CJK Compatibility Forms', + (0xFE50, 0xFE6F) : 'Small Form Variants', + (0xFE70, 0xFEFF) : 'Arabic Presentation Forms-B', + (0xFF00, 0xFFEF) : 'Halfwidth and Fullwidth Forms', + (0xFFF0, 0xFFFF) : 'Specials', + (0x10000, 0x1007F) : 'Linear B Syllabary', + (0x10080, 0x100FF) : 'Linear B Ideograms', + (0x10100, 0x1013F) : 'Aegean Numbers', + (0x10300, 0x1032F) : 'Old Italic', + (0x10330, 0x1034F) : 'Gothic', + (0x10380, 0x1039F) : 'Ugaritic', + (0x10400, 0x1044F) : 'Deseret', + (0x10450, 0x1047F) : 'Shavian', + (0x10480, 0x104AF) : 'Osmanya', + (0x10800, 0x1083F) : 'Cypriot Syllabary', + (0x1D000, 0x1D0FF) : 'Byzantine Musical Symbols', + (0x1D100, 0x1D1FF) : 'Musical Symbols', + (0x1D300, 0x1D35F) : 'Tai Xuan Jing Symbols', + (0x1D400, 0x1D7FF) : 'Mathematical Alphanumeric Symbols', + (0x20000, 0x2A6DF) : 'CJK Unified Ideographs Extension B', + (0x2F800, 0x2FA1F) : 'CJK Compatibility Ideographs Supplement', + (0xE0000, 0xE007F) : 'Tags', + } + + alphabet = [ + chr(code_point) for current_range in UNICODE_RANGES_MAP.keys() + for code_point in range(current_range[0], current_range[1] + 1) + ] + return ''.join(random.choice(alphabet) for i in range(length)) + + +#----------------------------------------------------------- +def send_keys_to_window(window_title, keys_to_send): + window_id = win32gui.FindWindow(None, window_title) + assert window_id > 0, f"Window with title '{window_title}' not found. Script must run only when user is logged on." + + win32gui.SetForegroundWindow(window_id) + time.sleep(0.1) # Give the window time to activate + + for key in keys_to_send: + if key.isupper(): + win32gui.SendMessage(window_id, win32con.WM_KEYDOWN, win32con.VK_SHIFT, 0) + win32gui.SendMessage(window_id, win32con.WM_CHAR, ord(key), 0) + win32gui.SendMessage(window_id, win32con.WM_KEYUP, win32con.VK_SHIFT, 0) + elif key == '\n': + win32gui.SendMessage(window_id, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0) + win32gui.SendMessage(window_id, win32con.WM_KEYUP, win32con.VK_RETURN, 0) + else: + win32gui.SendMessage(window_id, win32con.WM_CHAR, ord(key), 0) +#----------------------------------------------------------- + +MAX_WAIT_FOR_ISQL_FINISH_S = 20 + +test_script = """ +""" + +act = python_act('db', substitutions=[ ('[ \\t]+', ' ') ]) + +isql_out = temp_file('tmp_8524.log') +isql_bat = temp_file('tmp_8524.bat') +utf8_dat = temp_file('tmp_8524.dat') # for debug only + +expected_stdout = """ +""" + +@pytest.mark.version('>=6.0') +@pytest.mark.platform('Windows') +@pytest.mark.skip("Can not run when user is logged out. Child process must run in console window.") + +def test_1(act: Action, isql_out: Path, utf8_dat: Path, isql_bat: Path, capsys): + + # ::: ACHTUNG ::: + # The whole data that will be pasted in ISQL console must not have two same adjacent characters. + # For example, 'commit' will be 'comit' --> token unknown etc. + # The same for unicode string: second character (of two adjacent ones) will be 'swallowed'! + # The reason of this weird behaviour remained unknown. + # + #long_utf8_data = ''.join(set(get_random_unicode(8190))) + + long_utf8_data = '∑∏Ω' * (8191//3) + checked_char_len = len(long_utf8_data) + send_sql = f""" + set names utf8; + set list on; + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + show version; + recreate table test( s_utf8 varchar(8191) ); + out {str(isql_out)}; + insert into test(s_utf8) values( + '{long_utf8_data}' + ) returning char_length(s_utf8); + out; + exit; + + """ + + with open(utf8_dat, 'w', encoding = 'utf8') as f: + f.write(send_sql) + + # Child processes cmd.exe or isql.exe will use code page = 866. + # We have to set BEFOREHAND codepage = 65001 otherwise 'malformed string' will raise in ISQL console, even when use charset = utf8. + # To to this, we have to launch as child process BATCH file rather than just cmd.exe because there is no way to start sopmewhat like + # 'cmd.exe /cp 65001' with set needed codepage at one command. + # + launch_commands = f""" + cls + chcp 65001 + {act.vars['isql']} -q + exit + """ + with open(isql_bat, 'w') as f: + f.write(launch_commands) + + + # WRONG (can lead to 'malformed string' because we did not set codepage to 65001): + #p_child = subprocess.run( [ 'cmd.exe', '/c', 'start', act.vars['isql'], '-q' ] ) # , stdout = f, stderr = subprocess.STDOUT) + + p_child = subprocess.run( [ 'cmd.exe', '/c', 'start', str(isql_bat) ] ) + time.sleep(1) + + # ----------------------------------------------------------- + # ::: NB ::: + # Every line of (i.e. text to be pasted in console of ISQL) must be prefixed with TWO characters: ascii_char(13) and ascii_char(10). + # It is NOT enough to use as prefix only CHR_10 at this case! + # ----------------------------------------------------------- + + #send_keys_to_window( str(act.vars['isql']), '\r\n'.join( [x.lstrip() for x in send_sql.splitlines()] ) ) + send_keys_to_window( os.getenv('SystemRoot') + '\\system32\\cmd.exe - ' + str(isql_bat), '\r\n'.join( [x.lstrip() for x in send_sql.splitlines()] ) ) + + time.sleep(1) + try: + p_child.wait(MAX_WAIT_FOR_ISQL_FINISH_S) + p_child.terminate() + except AttributeError: # 'CompletedProcess' object has no attribute 'wait' + pass + + with open(isql_out, mode='r') as f: + for line in f: + print(line) + + act.expected_stdout = f""" + CHAR_LENGTH {checked_char_len} + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 18c27725b847f46803c631e86e317bc5ae7b1e32 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 27 May 2025 17:30:04 +0300 Subject: [PATCH 0513/1064] Added/Updated tests\bugs\gh_8524_test.py: reduced min_version. Added comments. --- tests/bugs/gh_8524_test.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_8524_test.py b/tests/bugs/gh_8524_test.py index f728d941..995273c8 100644 --- a/tests/bugs/gh_8524_test.py +++ b/tests/bugs/gh_8524_test.py @@ -12,13 +12,13 @@ exit ========== This batch further is called as CHILD process via: 'cmd.exe /c start ' which will launch ISQL. - ISQL process will have console window (which will appear on screen) and we wioll try to paste some text in it. + ISQL process will have console window (which will appear on screen) and we will try to paste some text in it. Text may contain non-printable / non-readable characters, so we have to check not the result of pasting but - value of CHAR_LENGTH(). This is done by creating a table and using INSERT command: + the value of CHAR_LENGTH(). This is done by creating a table and using INSERT command: ========= insert into test(s_utf8) values( - '{long_utf8_data}' + '' ) returning char_length(s_utf8); ========= Result of this command is redirected to log. @@ -27,7 +27,8 @@ NOTES: [27.05.2025] pzotov 0. Package 'pywin32' must be installed for this test (pip install pywin32). - 1. Test was added just to be able to check result of pasting long text in existing ISQL console. + 1. Problem could be reproduced only on Windows. Emulation of PASTE required (PIPE will not show any problem). + 2. Test was added just to be able to check result of pasting long text in existing ISQL console. This test will not able to create console window if python was launched by scheduler and appropriate task has not set to: "Run only when user is logged on". Because of that, this test has '@pytest.mark.skip' marker. @@ -35,11 +36,11 @@ REMOVE OR COMMENT OUT THIS MARKER TO RUN THIS TEST ################################################## - 2. String that we want to be pasted into console must NOT have two adjacent characters, e.g. 'commit'. + 3. String that we want to be pasted into console must NOT have two adjacent characters, e.g. 'commit'. Otherwise only first of them will be actually pasted but others will be 'swallowed' for unknown reason. - 3. Every line of (i.e. text to be pasted in console of ISQL) must be prefixed with TWO characters: ascii_char(13) and ascii_char(10). + 4. Every line of (i.e. text to be pasted in console of ISQL) must be prefixed with TWO characters: ascii_char(13) and ascii_char(10). It is NOT enough to use as prefix only CHR_10 at this case! - 4. Command processor ('cmd.exe') must change code page to 65001 before running ISQL, thus we launch BATCH rather than just ISQL (as child process). + 5. Command processor ('cmd.exe') must change code page to 65001 before running ISQL, thus we launch BATCH rather than just ISQL (as child process). Checked on 6.0.0.789. """ @@ -225,7 +226,7 @@ def send_keys_to_window(window_title, keys_to_send): expected_stdout = """ """ -@pytest.mark.version('>=6.0') +@pytest.mark.version('>=4.0.6') @pytest.mark.platform('Windows') @pytest.mark.skip("Can not run when user is logged out. Child process must run in console window.") From 69921f08f90454a40fafb86d02576f92360ba026 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 27 May 2025 19:25:52 +0300 Subject: [PATCH 0514/1064] Added/Updated tests\bugs\gh_8524_test.py: moved import directives inside working function --- tests/bugs/gh_8524_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8524_test.py b/tests/bugs/gh_8524_test.py index 995273c8..ce44d182 100644 --- a/tests/bugs/gh_8524_test.py +++ b/tests/bugs/gh_8524_test.py @@ -47,8 +47,6 @@ import os import random -import win32gui -import win32con import subprocess import time from pathlib import Path @@ -194,6 +192,10 @@ def get_random_unicode(length): #----------------------------------------------------------- def send_keys_to_window(window_title, keys_to_send): + + import win32gui + import win32con + window_id = win32gui.FindWindow(None, window_title) assert window_id > 0, f"Window with title '{window_title}' not found. Script must run only when user is logged on." From d460c0fff14d83e92db9e37d443b539eadd1ca3d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 31 May 2025 19:37:56 +0300 Subject: [PATCH 0515/1064] Added/Updated tests\bugs\gh_8579_test.py: Checked on 6.0.0.792-d90992f. DONE WITH CAVEATS - SEE NOTES. --- tests/bugs/gh_8579_test.py | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/bugs/gh_8579_test.py diff --git a/tests/bugs/gh_8579_test.py b/tests/bugs/gh_8579_test.py new file mode 100644 index 00000000..e5f9c702 --- /dev/null +++ b/tests/bugs/gh_8579_test.py @@ -0,0 +1,77 @@ +#coding:utf-8 + +""" +ID: issue-8579 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8579 +TITLE: Add sub routines info in the BLR debug blob filter +DESCRIPTION: + Test creates procedure (sp_main) and function (fn_main) and each contains declarations + of inner procedures and functions. + Then we run query 'select rdb$debug_info from rdb$...' and check that line line 'BLR to Source mapping:' + occurs exactly times for each kind sub-routine. +NOTES: + [31.05.2025] pzotov + If we try to declare inner procedures 19 times then line 'BLR to Source mapping:' appears to be "broken" + for last (19th) sub-routine. Because of this, test currently must use no more than 18 declarations. + Sent report to Adriano, waiting for fix. + + Checked on 6.0.0.792-d90992f. +""" +import pytest +from firebird.qa import * + +SUBROUTINES_COUNT = 18 # 31.05.2025: 19 - broken line 'BLR to Source mapping:' ! +BLR_TO_SOURCE_TXT = 'BLR to Source mapping:' +substitutions = [ ('^((?!' + BLR_TO_SOURCE_TXT + '|Sub function|Sub procedure).)*$', '') ] + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_lst = [] + +proc_ddl = [ 'create procedure sp_main as' ] +for i in range(SUBROUTINES_COUNT): + proc_ddl.extend( [f' declare function sp_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) + expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub function SP_MAIN_SUB_FUNC_{i:05}:']) + +for i in range(SUBROUTINES_COUNT): + proc_ddl.extend( [f' declare procedure sp_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) + expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub procedure SP_MAIN_SUB_PROC_{i:05}:']) +proc_ddl.extend( ['begin', 'end'] ) + +expected_lst.append(BLR_TO_SOURCE_TXT) + +#.......................................................................................... + +func_ddl = [ 'create function fn_main returns int as' ] +for i in range(SUBROUTINES_COUNT): + func_ddl.extend( [f' declare function fn_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) + expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub function FN_MAIN_SUB_FUNC_{i:05}:']) + +for i in range(SUBROUTINES_COUNT): + func_ddl.extend( [f' declare procedure fn_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) + expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub procedure FN_MAIN_SUB_PROC_{i:05}:']) +func_ddl.extend( ['begin', ' return 1;', 'end'] ) + +expected_lst.append(BLR_TO_SOURCE_TXT) + +#----------------------------------------------------------------------------------------- + +@pytest.mark.version('>=6.0') +def test_1(act: Action, capsys): + + with act.db.connect(charset = 'utf8') as con: + con.execute_immediate('\n'.join([x.strip() for x in proc_ddl])) + con.execute_immediate('\n'.join([x.strip() for x in func_ddl])) + con.commit() + + sources_map = { 'rdb$procedures' : ('rdb$procedure_name', 'sp_main'), 'rdb$functions' : ('rdb$function_name', 'fn_main') } + for k,v in sources_map.items(): + check_sql = f"set heading off; set blob all; select p.rdb$debug_info as blob_debug_info from {k} p where p.{v[0]} = upper('{v[1]}');" + act.isql(switches = ['-q'], input = check_sql, combine_output = True) + print(act.stdout) + act.reset() + + act.expected_stdout = '\n'.join(expected_lst) + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 5fe740c4e567ac70bb273fd1baacea1ee1146945 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Jun 2025 11:08:03 +0300 Subject: [PATCH 0516/1064] Added/Updated tests\bugs\core_6142_test.py: Re-implemented in order to see details about failed attachments (accumulate them in separate logs and print at final of test). --- tests/bugs/core_6142_test.py | 152 ++++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 56 deletions(-) diff --git a/tests/bugs/core_6142_test.py b/tests/bugs/core_6142_test.py index e2eb46e1..a63a5f4e 100644 --- a/tests/bugs/core_6142_test.py +++ b/tests/bugs/core_6142_test.py @@ -21,18 +21,41 @@ FBTEST: bugs.core_6142 NOTES: [20.08.2022] pzotov - Confirmed again problem with 4.0.0.1598, 3.0.5.33166. - Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 + Confirmed again problem with 4.0.0.1598, 3.0.5.33166. + Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 + + [02.06.2025] pzotov + Re-implemented in order to see details about failed attachments (accumulate them in separate logs and print at final of test). + Checked on 6.0.0.795 + + ::: NB ::: + Weird message after test summary if we try to raise connection problem using invalid password (in order to check output): + ========== + Exception ignored in atexit callback: + Traceback (most recent call last): + File "C:/Python3x/Lib/site-packages/firebird/driver/core.py", line 161, in _api_shutdown + provider.shutdown(0, -3) # fb_shutrsn_app_stopped + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:/Python3x/Lib/site-packages/firebird/driver/interfaces.py", line 1315, in shutdown + self._check() + File "C:/Python3x/Lib/site-packages/firebird/driver/interfaces.py", line 113, in _check + raise self.__report(DatabaseError, self.status.get_errors()) + firebird.driver.types.DatabaseError: connection shutdown + ========== + Problem exists on both SS and CS. + The reason currently remains unknown. """ import os import threading import datetime as py_dt +from typing import List +from pathlib import Path import time import pytest from firebird.qa import * -from firebird.driver import connect, driver_config, NetProtocol +from firebird.driver import connect, driver_config, NetProtocol, DatabaseError ########################### ### S E T T I N G S ### @@ -44,89 +67,95 @@ # Number of iterations to make connect / disconnect for every started thread: LOOP_CNT = 10 +############################## +DEBUG_USE_INVALID_PASSWORD = 0 +############################## + +tmp_logs = temp_files( [ f'tmp_6142.{i}.log' for i in range(THREADS_CNT) ] ) tmp_user = user_factory('db', name='tmp$core_6142', password='123', plugin = 'Srp') db = db_factory() -act = python_act('db', substitutions=[('[ \t]+', ' '), ('^((?!SQLCODE|SQLSTATE|[Cc]onnection|OVERALL RESULT).)*$', '')]) +act = python_act('db') #--------------------- def showtime(): - return ''.join( (py_dt.datetime.now().strftime("%H:%M:%S.%f")[:11],'.') ) + return ''.join( (py_dt.datetime.now().strftime("%H:%M:%S.%f")[:11],'. ') ) #--------------------- -class workerThread(threading.Thread): - def __init__(self, db_cfg_object, thr_idx, threads_cnt, num_of_iterations, usr): - threading.Thread.__init__(self) - self.db_cfg_object = db_cfg_object - self.thr_idx = thr_idx - self.threads_cnt = threads_cnt - self.num_of_iterations = num_of_iterations - self.usr = usr - - self.results_dict = { thr_idx : [0,0] } - #fb_cset_lst = ['dos437', 'dos850', 'dos865', 'dos852', 'dos857', 'dos860','dos861', 'dos863', 'dos737', 'dos775', 'dos858', 'dos862', 'dos864', 'dos866', 'dos869', 'win1250', 'win1251', 'win1252', 'win1253', 'win1254', 'win1255', 'win1256', 'win1257', 'iso_8859_1', 'iso_8859_2', 'iso_8859_3', 'iso_8859_4', 'iso_8859_5', 'iso_8859_6', 'iso_8859_7', 'iso_8859_8', 'iso_8859_9'] - #self.db_cfg_object.charset.value = fb_cset_lst[thr_idx] - - def run(self): - print( showtime(), f"Starting thread {self.thr_idx} / {self.threads_cnt}" ) - make_db_attach(self) - print( showtime(), f"Exiting thread {self.thr_idx} / {self.threads_cnt}" ) - - def show_results(self): - for k,v in sorted( self.results_dict.items() ): - print( "ID of thread: %3d. OVERALL RESULT: PASSED=%d, FAILED=%d" % ( k, v[0], v[1] ) ) +def make_db_attach(thread_object): -#--------------------- + mon_sql = f"select count(*) from mon$attachments where mon$user = '{thread_object.tmp_user.name.upper()}'" -def make_db_attach(thread_object): + with open(thread_object.tmp_log,'a') as f_thread_log: - i = 0 - mon_sql = f"select count(*) from mon$attachments where mon$user = '{thread_object.usr.name.upper()}'" + for iter in range(thread_object.num_of_iterations): + msg_prefix = f"Thread {thread_object.thr_idx}, iter {iter}/{thread_object.num_of_iterations-1}" + f_thread_log.write( showtime() + f"{msg_prefix} - trying to make connection\n" ) + con = None + try: + a_pass = thread_object.tmp_user.password + if DEBUG_USE_INVALID_PASSWORD and thread_object.thr_idx == 2 and iter % 3 == 0: + a_pass = 't0ta11y@wrong' - while i < thread_object.num_of_iterations: + with connect( thread_object.db_cfg_object.name, user = thread_object.tmp_user.name, password = a_pass ) as con: + f_thread_log.write( showtime() + f"{msg_prefix} - established, {con.info.id=}\n" ) - con = None - att = 0 + # Accumulate counter of SUCCESSFULY established attachments: + thread_object.pass_lst.append(iter) - msg_prefix = f"Thread {thread_object.thr_idx}, iter {i}/{thread_object.num_of_iterations-1}" - print( showtime(), f"{msg_prefix} - trying to connect" ) + except DatabaseError as e: + # Accumulate counter of FAILED attachments: + thread_object.fail_lst.append(iter) + f_thread_log.write(f'### EXCEPTION ###\n') + f_thread_log.write(e.__str__() + '\n') + for x in e.gds_codes: + f_thread_log.write(str(x) + '\n') - try: - with connect( thread_object.db_cfg_object.name, user = thread_object.usr.name, password = thread_object.usr.password ) as con: - print( showtime(), f"{msg_prefix}: created att = {con.info.id}" ) # , charset = {con.charset}" ) +#--------------------- - # Accumulate counter of SUCCESSFULY established attachments: - thread_object.results_dict[ thread_object.thr_idx ][0] += 1 +class workerThread(threading.Thread): + def __init__(self, db_cfg_object, thr_idx, threads_cnt, num_of_iterations, tmp_user, tmp_logs): + threading.Thread.__init__(self) + self.db_cfg_object = db_cfg_object + self.thr_idx = thr_idx + self.threads_cnt = threads_cnt + self.num_of_iterations = num_of_iterations + self.tmp_user = tmp_user + self.tmp_log = tmp_logs[thr_idx] + + self.pass_lst = [] + self.fail_lst = [] - except Exception as e: - # Accumulate counter of FAILED attachments: - thread_object.results_dict[ thread_object.thr_idx ][1] += 1 - print(e) + def run(self): + with open(self.tmp_log, 'w') as f_thread_log: + f_thread_log.write( showtime() + f"Starting thread {self.thr_idx} / {self.threads_cnt-1}\n" ) + + make_db_attach(self) + with open(self.tmp_log, 'a') as f_thread_log: + f_thread_log.write( showtime() + f"Exiting thread {self.thr_idx} / {self.threads_cnt-1}\n" ) - i += 1 #--------------------- - @pytest.mark.version('>=3.0.5') @pytest.mark.platform('Windows') -def test_1(act: Action, tmp_user: User, capsys): +def test_1(act: Action, tmp_user: User, tmp_logs: List[Path], capsys): srv_config = driver_config.register_server(name = 'test_srv_core_6142', config = '') # Create new threads: # ################### threads_list=[] - for thr_idx in range(0, THREADS_CNT): + for thr_idx in range(THREADS_CNT): db_cfg_object = driver_config.register_database(name = f'test_db_core_6142_{thr_idx}') db_cfg_object.database.value = str(act.db.db_path) db_cfg_object.server.value = 'test_srv_core_6142' db_cfg_object.protocol.value = NetProtocol.XNET - threads_list.append( workerThread( db_cfg_object, thr_idx, THREADS_CNT, LOOP_CNT, tmp_user ) ) + threads_list.append( workerThread( db_cfg_object, thr_idx, THREADS_CNT, LOOP_CNT, tmp_user, tmp_logs ) ) # Start new Threads # ################# @@ -137,12 +166,23 @@ def test_1(act: Action, tmp_user: User, capsys): for t in threads_list: t.join() - act.expected_stdout = '' - for t in threads_list: - t.show_results() - act.expected_stdout += 'ID of thread: %d. OVERALL RESULT: PASSED=%d, FAILED=%d\n' % (t.thr_idx, LOOP_CNT, 0) - - #print( showtime(), "##### Exiting Main Thread #####\\n") - + # not helps -- time.sleep(151) + + if set([len(t.pass_lst) for t in threads_list]) == set((LOOP_CNT,)): + # All threads could establish connections using XNET on iterations. + print('Expected.') + else: + for t in threads_list: + if t.fail_lst: + print(f'Thread {t.thr_idx} - failed attempts to make connection on iterations:') + print(t.fail_lst) + print('Check log:') + with open(t.tmp_log, 'r') as f: + print(f.read()) + print('*' * 50) + + act.expected_stdout = """ + Expected. + """ act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 8e018ff558f12f269a7a10de738ef9433369b0da Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Jun 2025 12:04:42 +0300 Subject: [PATCH 0517/1064] Added/Updated tests\bugs\core_6142_test.py: Renamings. Added second case for DEBUG_KIND_OF_INVALID_DATA --- tests/bugs/core_6142_test.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_6142_test.py b/tests/bugs/core_6142_test.py index a63a5f4e..d84c82ae 100644 --- a/tests/bugs/core_6142_test.py +++ b/tests/bugs/core_6142_test.py @@ -29,7 +29,8 @@ Checked on 6.0.0.795 ::: NB ::: - Weird message after test summary if we try to raise connection problem using invalid password (in order to check output): + Special setting DEBUG_KIND_OF_INVALID_DATA presents in this test in order to force connection to be failed and check output. + When this setting is 'invalid_pass' then weird message after test summary: ========== Exception ignored in atexit callback: Traceback (most recent call last): @@ -42,7 +43,9 @@ raise self.__report(DatabaseError, self.status.get_errors()) firebird.driver.types.DatabaseError: connection shutdown ========== - Problem exists on both SS and CS. + Problem exists on 4.x ... 6.x (SS/CS). + No such message if we set DEBUG_KIND_OF_INVALID_DATA = 'not_valid_db' and try to make connection to some file that for is not valid .fdb + The reason currently remains unknown. """ @@ -68,7 +71,9 @@ LOOP_CNT = 10 ############################## -DEBUG_USE_INVALID_PASSWORD = 0 +DEBUG_KIND_OF_INVALID_DATA = '' # 'not_valid_db' / 'invalid_pass' +#DEBUG_KIND_OF_INVALID_DATA = 'not_valid_db' +#DEBUG_KIND_OF_INVALID_DATA = 'invalid_pass' ############################## tmp_logs = temp_files( [ f'tmp_6142.{i}.log' for i in range(THREADS_CNT) ] ) @@ -93,11 +98,17 @@ def make_db_attach(thread_object): for iter in range(thread_object.num_of_iterations): msg_prefix = f"Thread {thread_object.thr_idx}, iter {iter}/{thread_object.num_of_iterations-1}" f_thread_log.write( showtime() + f"{msg_prefix} - trying to make connection\n" ) - con = None + + db_bak = thread_object.db_cfg_object.database.value # need for DEBUG_KIND_OF_INVALID_DATA == 'not_valid_db' try: a_pass = thread_object.tmp_user.password - if DEBUG_USE_INVALID_PASSWORD and thread_object.thr_idx == 2 and iter % 3 == 0: - a_pass = 't0ta11y@wrong' + if DEBUG_KIND_OF_INVALID_DATA and thread_object.thr_idx == 2 and iter % 3 == 0: + if DEBUG_KIND_OF_INVALID_DATA == 'not_valid_db': + thread_object.db_cfg_object.database.value = str(thread_object.tmp_act.vars['bin-dir'] / 'fbclient.dll') + elif DEBUG_KIND_OF_INVALID_DATA == 'invalid_pass': + a_pass = 't0ta11y@wrong' + else: + pass with connect( thread_object.db_cfg_object.name, user = thread_object.tmp_user.name, password = a_pass ) as con: f_thread_log.write( showtime() + f"{msg_prefix} - established, {con.info.id=}\n" ) @@ -112,11 +123,13 @@ def make_db_attach(thread_object): f_thread_log.write(e.__str__() + '\n') for x in e.gds_codes: f_thread_log.write(str(x) + '\n') + finally: + thread_object.db_cfg_object.database.value = db_bak #--------------------- class workerThread(threading.Thread): - def __init__(self, db_cfg_object, thr_idx, threads_cnt, num_of_iterations, tmp_user, tmp_logs): + def __init__(self, act: Action, db_cfg_object, thr_idx, threads_cnt, num_of_iterations, tmp_user, tmp_logs): threading.Thread.__init__(self) self.db_cfg_object = db_cfg_object self.thr_idx = thr_idx @@ -125,6 +138,7 @@ def __init__(self, db_cfg_object, thr_idx, threads_cnt, num_of_iterations, tmp_u self.tmp_user = tmp_user self.tmp_log = tmp_logs[thr_idx] + self.tmp_act = act self.pass_lst = [] self.fail_lst = [] @@ -155,7 +169,7 @@ def test_1(act: Action, tmp_user: User, tmp_logs: List[Path], capsys): db_cfg_object.server.value = 'test_srv_core_6142' db_cfg_object.protocol.value = NetProtocol.XNET - threads_list.append( workerThread( db_cfg_object, thr_idx, THREADS_CNT, LOOP_CNT, tmp_user, tmp_logs ) ) + threads_list.append( workerThread( act, db_cfg_object, thr_idx, THREADS_CNT, LOOP_CNT, tmp_user, tmp_logs ) ) # Start new Threads # ################# From 7cf42b201afa28dbc349e6c5fa52cdb1aee30b51 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 2 Jun 2025 20:25:07 +0300 Subject: [PATCH 0518/1064] Added/Updated tests\functional\tabloid\test_ibp_124.py: Additional test for GH-6057 aka CORE-5794: add implicit savepoint, see notes. --- tests/functional/tabloid/test_ibp_124.py | 98 ++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/functional/tabloid/test_ibp_124.py diff --git a/tests/functional/tabloid/test_ibp_124.py b/tests/functional/tabloid/test_ibp_124.py new file mode 100644 index 00000000..c6dec8bf --- /dev/null +++ b/tests/functional/tabloid/test_ibp_124.py @@ -0,0 +1,98 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: WHERE CURRENT OF within block that has savepoint: statement #2 must see changes produced by statement #1 +DESCRIPTION: + Original issue: + https://quality.embarcadero.com/projects/IBP/issues/IBP-124?filter=allopenissues&orderby=priority+ASC%2C+updated+DESC +NOTES: + [02.06.2025] pzotov + 1. Test has similar code to described in CORE-5794 (GH-6057) but adds WHEN-block in order to create implicit savepoint. + This causes changes that have been done by statement #1 to be seen for (same) cursor when it runs statement #2. + 2. Difference of this begaviour (comparing to 2.5) relates to CURSOR STABILITY feature that appeared since 3.x + Workaround was provided by hvlad, see: + https://github.com/FirebirdSQL/firebird/issues/6057#issuecomment-826242377 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + create or alter procedure sp_test as begin end; + recreate table test ( + id int generated by default as identity, + data1 int, + data2 int + ); + recreate table dml_audit(log_id int generated by default as identity, log_msg varchar(255)); + + set term ^; + create trigger trg_test_bu0 for test active before update position 0 as + declare log_msg type of column dml_audit.log_msg; + begin + log_msg = + 'old.data1: ' || old.data1 || + ', new.data1: ' || new.data1 || + ', old.data2: ' || old.data2 || + ', new.data2: ' || new.data2 + ; + insert into dml_audit(log_msg) values(:log_msg); + end + ^ + create or alter procedure sp_test as + declare var_id integer; + begin + for + select t.id from test t where t.id = 1 + into + :var_id + as cursor + cur_tst + do + begin + update test t set t.data1 = 1 -- ....... statement #1 + where current of cur_tst; + + update test t set t.data2 = 2 -- ....... statement #2 + where current of cur_tst; + + -- following 'when'-block causes engine to create implicit savepoint and + -- changed value of data1 will be seen here. + -- Without this block value of 'DATA1' column will be seen here as old one, i.e. 0. + -- https://github.com/FirebirdSQL/firebird/issues/6057#issuecomment-826242377 + when any do + exception; + end + end ^ + set term ;^ + commit; + + insert into test (data1, data2) values (0, 0); + execute procedure sp_test; + + select * from test; + select * from dml_audit; +""" + +act = isql_act('db', test_script) + +expected_stdout = """ + ID 1 + DATA1 1 + DATA2 2 + + LOG_ID 1 + LOG_MSG old.data1: 0, new.data1: 1, old.data2: 0, new.data2: 0 + LOG_ID 2 + LOG_MSG old.data1: 1, new.data1: 1, old.data2: 0, new.data2: 2 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From dd698aa5886e218714d980c4bcaa8690078e043f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:34:43 +0300 Subject: [PATCH 0519/1064] Added/Updated tests\functional\sqlancer\arch_2312_17510_example_01_test.py: adapted from article provided in SQLancer documentation. --- .../arch_2312_17510_example_01_test.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/functional/sqlancer/arch_2312_17510_example_01_test.py diff --git a/tests/functional/sqlancer/arch_2312_17510_example_01_test.py b/tests/functional/sqlancer/arch_2312_17510_example_01_test.py new file mode 100644 index 00000000..aff2070b --- /dev/null +++ b/tests/functional/sqlancer/arch_2312_17510_example_01_test.py @@ -0,0 +1,48 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://arxiv.org/pdf/2312.17510 +TITLE: PARTIAL INDICES. NATURAL RIGHT JOIN results in an unexpected "Unknown column" error +DESCRIPTION: + https://arxiv.org/pdf/2312.17510 page #2 listing 1 +NOTES: + [05.06.2025] pzotov + Support for partial indices in FB: + https://github.com/FirebirdSQL/firebird/pull/7257 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + --Listing 1. A bug found by QPG in SQLite due to an incorrect use of an + --index in combination with a JOIN. Given the same SELECT, the left query + --plan is produced if no index is present, while the right one uses the index. + CREATE TABLE t1(a INT, b INT); + CREATE TABLE t2(c INT); + CREATE TABLE t3(d INT); + + INSERT INTO t1(a) VALUES(2); + INSERT INTO t3 VALUES(1); + commit; + + CREATE INDEX i0 ON t2(c) + WHERE c = 3 -- ::: NB ::: partial index + ; + + SELECT * + FROM t2 + RIGHT JOIN t3 ON d <> 0 + LEFT JOIN t1 ON c = 3 + WHERE t1.a <> 0; -- output must be empty resultset +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=5.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From 76e2958300047b9af516c7c3b5e4c0616bbebb6c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:34:50 +0300 Subject: [PATCH 0520/1064] Added/Updated tests\functional\sqlancer\arch_2312_17510_example_02_test.py: adapted from article provided in SQLancer documentation. --- .../arch_2312_17510_example_02_test.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/functional/sqlancer/arch_2312_17510_example_02_test.py diff --git a/tests/functional/sqlancer/arch_2312_17510_example_02_test.py b/tests/functional/sqlancer/arch_2312_17510_example_02_test.py new file mode 100644 index 00000000..afa7a483 --- /dev/null +++ b/tests/functional/sqlancer/arch_2312_17510_example_02_test.py @@ -0,0 +1,46 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://arxiv.org/pdf/2312.17510 +TITLE: Bug in RIGHT JOIN +DESCRIPTION: + https://arxiv.org/pdf/2312.17510 page #7 listing 2 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + CREATE TABLE t1(a CHAR); + CREATE TABLE t2(b CHAR); + CREATE TABLE t3(c CHAR NOT NULL); + CREATE TABLE t4(d CHAR); + + INSERT INTO t2 VALUES('x'); + INSERT INTO t3 VALUES('y'); + + SELECT * + FROM t4 + LEFT JOIN t3 ON TRUE + INNER JOIN t1 ON t3.c='' + RIGHT JOIN t2 ON t3.c='' + WHERE t3.c IS NULL; + +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + D + C + A + B x + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 09940f48ba4c4059ea9607bad71684fb5dcd6998 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:34:55 +0300 Subject: [PATCH 0521/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_01_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_01_test.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_01_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_01_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_01_test.py new file mode 100644 index 00000000..032e1a87 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_01_test.py @@ -0,0 +1,59 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: predicate 0 = -0 to incorrectly evaluate to FALSE. +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 2 listing 1 +NOTES: + [01.06.2025] pzotov + Bug exists on Firebird 3.0.13.33807 (18.04.2025). +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 ( c0 int ); + recreate table t1 ( c0 double precision ); + commit; + + insert into t0 values (0) ; + insert into t1 values ( -0e0 ); + + -- select (t0.c0 = t1.c0) is true from t0 cross join t1; + set count on; + + select t0.c0 as q1_t0_c0, t1.c0 as q1_t1_c0 + from t0 cross join t1 where t0.c0 = t1.c0 ; -- expected: {0, -0}; found: {} + ---------------------------------------------------------------------- + select t0.c0 as q2_t0_c0, t1.c0 as q2_t1_c0 from t0 cross join t1 where t0.c0 = t1.c0 + union all + select * from t0 cross join t1 where not ( t0.c0 = t1.c0 ) + union all + select * from t0 cross join t1 where ( t0.c0 = t1.c0 ) is null ; -- -- expected: {0, -0}; found: {} + ---------------------------------------------------------------------- +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0') +def test_1(act: Action): + act.expected_stdout = """ + Q1_T0_C0 0 + Q1_T1_C0 -0.000000000000000 + Records affected: 1 + + Q2_T0_C0 0 + Q2_T1_C0 -0.000000000000000 + Records affected: 1 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e593ab8cbc3a69fd5be250069f621bd8cb37e8a9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:01 +0300 Subject: [PATCH 0522/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_02_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_02_test.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_02_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_02_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_02_test.py new file mode 100644 index 00000000..cf09d845 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_02_test.py @@ -0,0 +1,53 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Wrong result of UNION DISTINCT +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 10 listing 2 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate view v0 as select 1 x from rdb$database; + recreate table t0 ( c0 int ); + recreate view v0 as select cast ( t0.c0 as integer ) as c0 from t0; + + insert into t0 ( c0 ) values (0); + + set count on; + + select distinct t0.c0 as q1_table_c0, v0.c0 as q1_view_c0 + from t0 left outer join v0 on v0.c0 >= '0'; -- expected = found = {0|0} + + select t0.c0 as q2_table_c0, v0.c0 as q2_view_c0 from t0 left outer join v0 on v0.c0 >= '0' where true + union + select * from t0 left join v0 on v0.c0 >= '0' where not true + union + select * from t0 left join v0 on v0.c0 >= '0' where true is null ; -- expected: {0|0}, found: {0|null} +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + Q1_TABLE_C0 0 + Q1_VIEW_C0 0 + Records affected: 1 + + Q2_TABLE_C0 0 + Q2_VIEW_C0 0 + Records affected: 1 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 37a89d340784ed762d87267ff44e34d4e1ceba7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:07 +0300 Subject: [PATCH 0523/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_04_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_04_test.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_04_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_04_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_04_test.py new file mode 100644 index 00000000..b5a3a846 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_04_test.py @@ -0,0 +1,54 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Wrong result of AVG evaluation as result of SUM / COUNT +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 11 listing 4 +NOTES: + [01.06.2025] pzotov + Bug exists on Firebird 3.0.13.33807 (18.04.2025): + Statement failed, SQLSTATE = 22003 + Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + + recreate table t0 ( c0 bigint ); + insert into t0 (c0) values (2) ; + insert into t0 (c0) values (9223372036854775807) ; + select avg (t0.c0) as avg_func from t0; + commit; + + select sum (s)/ sum (c) as avg_eval + from ( + select sum ( t0.c0 ) as s , count ( t0.c0 ) as c from t0 where c0 > 0 + union all + select sum ( t0.c0 ) as s , count ( t0.c0 ) as c from t0 where not (c0 > 0) + union all + select sum ( t0.c0 ) as s , count ( t0.c0 ) as c from t0 where c0 is null + ); -- { -4611686018427387903} + commit; + +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0') +def test_1(act: Action): + act.expected_stdout = """ + AVG_FUNC 4611686018427387904 + AVG_EVAL 4611686018427387904 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 6b7afbe5de588376b97052296b1fb8c752c632b4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:12 +0300 Subject: [PATCH 0524/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_06_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_06_test.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_06_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_06_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_06_test.py new file mode 100644 index 00000000..38a82836 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_06_test.py @@ -0,0 +1,38 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Failed to fetch a row from a view. +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 12 listing 6 +NOTES: +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 (c0 int); + recreate view v0 as select t0.c0, true as c1 from t0; + insert into t0 values (0); + select v0.c0 from v0 cross join t0 where v0.c1; + commit; + +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 0 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0760ad11dc03eb4ac54010cf80b14a5f0e70e3f1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:17 +0300 Subject: [PATCH 0525/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_09_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_09_test.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_09_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_09_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_09_test.py new file mode 100644 index 00000000..3b1146b9 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_09_test.py @@ -0,0 +1,41 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: GROUP BY ignores COLLATE with case insensitive attribute +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 13 listing 9 +NOTES: +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + create collation name_coll for utf8 from unicode case insensitive; + create domain dm_test varchar(1) character set utf8 collate name_coll; + + create table t0 (c0 dm_test); + insert into t0 (c0) values ( 'a'); + insert into t0 (c0) values ( 'A'); + select count(*) as grouping_cnt from ( + select t0.c0 from t0 group by t0.c0 + ); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + GROUPING_CNT 1 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 95b12f4d26a9cd0b03ecbd8e15c527d5a928abd5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:22 +0300 Subject: [PATCH 0526/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_10_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_10_test.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_10_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_10_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_10_test.py new file mode 100644 index 00000000..7b7fe260 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_10_test.py @@ -0,0 +1,37 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Unnexpectedly optimized VARIANCE(0) to FALSE +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 14 listing 10 +NOTES: +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + create table t0 (c0 int); + insert into t0 (c0) values (0); + select t0.c0 + from t0 + group by t0.c0 + having not ( (select var_pop(0) from rdb$database where false) is null ); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0') +def test_1(act: Action): + act.expected_stdout = """ + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d62b1983f6855b31c168fd38e2c097dc7a078281 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:27 +0300 Subject: [PATCH 0527/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_11_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_11_test.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_11_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_11_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_11_test.py new file mode 100644 index 00000000..5588e6cc --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_11_test.py @@ -0,0 +1,53 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Non-deterministic output when using MAX() function +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 14 listing 11 +NOTES: +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 ( c0 int ); + recreate table t1 ( c0 varchar(100) ); + insert into t1 values (0.9201898334673894); + insert into t1 values (0); + insert into t0 values (0); + + select * + from t0 cross join t1 + group by t0.c0, t1.c0 + having t1.c0 != max(t1.c0) + + UNION ALL + + select * + from t0 cross join t1 + group by t0.c0, t1.c0 + having not t1.c0 > max (t1.c0) + ; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 0 + C0 0 + C0 0 + C0 0.9201898334673894 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 35c3642e980eb35313ee1bd6b376bac7f3b71696 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:33 +0300 Subject: [PATCH 0528/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_15_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_15_test.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_15_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_15_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_15_test.py new file mode 100644 index 00000000..4a4ae707 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_15_test.py @@ -0,0 +1,38 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Wrong evaluation of MIN when bitwise shift is applied to the source value +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 15 listing 15 +NOTES: +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 ( c0 int ); + insert into t0 values (-1) ; + commit; + select min(bin_shl(cast(c0 as bigint ),63)) as min_shl_63 from t0; + select min(bin_shl(cast(c0 as int128 ), 127)) as min_shl_127 from t0; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0') +def test_1(act: Action): + act.expected_stdout = """ + MIN_SHL_63 -9223372036854775808 + MIN_SHL_127 -170141183460469231731687303715884105728 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From b43a845e45bcf81d26df4616b053cc3d33716de4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:38 +0300 Subject: [PATCH 0529/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_17_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_17_test.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_17_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_17_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_17_test.py new file mode 100644 index 00000000..bf805c01 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_17_test.py @@ -0,0 +1,34 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Conversion of character string to boolean value +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 23 listing 17 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 (c0 boolean); + insert into t0 values (false); + select * from t0 where not (c0 != 'true' and c0); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e554b1212e2c260c17bf86d9bc234ae24b066702 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:43 +0300 Subject: [PATCH 0530/1064] Added/Updated tests\functional\sqlancer\doi_10_1145_3428279_example_18_test.py: adapted from article provided in SQLancer documentation. --- .../doi_10_1145_3428279_example_18_test.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/functional/sqlancer/doi_10_1145_3428279_example_18_test.py diff --git a/tests/functional/sqlancer/doi_10_1145_3428279_example_18_test.py b/tests/functional/sqlancer/doi_10_1145_3428279_example_18_test.py new file mode 100644 index 00000000..818271b3 --- /dev/null +++ b/tests/functional/sqlancer/doi_10_1145_3428279_example_18_test.py @@ -0,0 +1,40 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://dl.acm.org/doi/pdf/10.1145/3428279 +TITLE: Comparison of string and numeric literals +DESCRIPTION: + Manuel Rigger and Zhendong Su + Finding Bugs in Database Systems via Query Partitioning + https://dl.acm.org/doi/pdf/10.1145/3428279 + page 23 listing 18 +NOTES: + [02.06.2025] pzotov + This test issues only ONE row ('C0 -1') which differs from expected result shown in the source. + Sent report to dimitr et al. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail on; + set list on; + recreate table t0 (c0 varchar(2) unique); + insert into t0 values (-1); + insert into t0 values (-2); + select * from t0 where c0 >= -1; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 -1 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 55c89dbbd738c6844a19cdcf5b9eea6d0ab634a7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:48 +0300 Subject: [PATCH 0531/1064] Added/Updated tests\functional\sqlancer\osdi20_rigger_example_01_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/osdi20_rigger_example_01_test.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/functional/sqlancer/osdi20_rigger_example_01_test.py diff --git a/tests/functional/sqlancer/osdi20_rigger_example_01_test.py b/tests/functional/sqlancer/osdi20_rigger_example_01_test.py new file mode 100644 index 00000000..95db4db4 --- /dev/null +++ b/tests/functional/sqlancer/osdi20_rigger_example_01_test.py @@ -0,0 +1,40 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://www.usenix.org/system/files/osdi20-rigger.pdf +TITLE: Partial index must not use incorrect assumption that 'c0 IS NOT 1' implied 'c0 NOT NULL' +DESCRIPTION: + https://www.usenix.org/system/files/osdi20-rigger.pdf + page 3 listing 1 +NOTES: + [05.06.2025] pzotov + Support for partial indices in FB: + https://github.com/FirebirdSQL/firebird/pull/7257 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table t0 ( c0 int ); + create index i0 on t0 (c0) where c0 is not null; + insert into t0 values (0); + insert into t0 values (1); + insert into t0 values (null); + select c0 from t0 where c0 is distinct from 1; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=5.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 0 + C0 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a70e4e264f93efa05527b4953d8186410ba7faad Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:53 +0300 Subject: [PATCH 0532/1064] Added/Updated tests\functional\sqlancer\osdi20_rigger_example_04_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/osdi20_rigger_example_04_test.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/functional/sqlancer/osdi20_rigger_example_04_test.py diff --git a/tests/functional/sqlancer/osdi20_rigger_example_04_test.py b/tests/functional/sqlancer/osdi20_rigger_example_04_test.py new file mode 100644 index 00000000..8b0b034e --- /dev/null +++ b/tests/functional/sqlancer/osdi20_rigger_example_04_test.py @@ -0,0 +1,55 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://www.usenix.org/system/files/osdi20-rigger.pdf +TITLE: Incorrect result for DISTINCT. +DESCRIPTION: + https://www.usenix.org/system/files/osdi20-rigger.pdf + page 10 listing 4 + + COULD NOT REPRODUCE PROPER (EXPECTED) REQULT. SOURCE QUERY SYNTAX SEEMS WEIRD! +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + -- set list on; + recreate table t0 (c0 int, c1 int, c2 int, c3 int /* generated by default as identity */, unique (c3 ,c2 )); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(0); + insert into t0 ( c2 ) values(null); + insert into t0 ( c2 ) values(1); + insert into t0 ( c2 ) values(0); + + update t0 set c1 = 0; + insert into t0 ( c0 ) values (0); + insert into t0 ( c0 ) values (0); + insert into t0 ( c0 ) values (null); + insert into t0 ( c0 ) values (0); + + update t0 set c2 = 1; + select distinct * from t0 where c2 = 1; + +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.skip("Could not reproduce expected output. Source query syntax seems weird") +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 55150512cc208f67f02782b4837896b0365b0ca1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:35:59 +0300 Subject: [PATCH 0533/1064] Added/Updated tests\functional\sqlancer\osdi20_rigger_example_05_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/osdi20_rigger_example_05_test.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/functional/sqlancer/osdi20_rigger_example_05_test.py diff --git a/tests/functional/sqlancer/osdi20_rigger_example_05_test.py b/tests/functional/sqlancer/osdi20_rigger_example_05_test.py new file mode 100644 index 00000000..9173496f --- /dev/null +++ b/tests/functional/sqlancer/osdi20_rigger_example_05_test.py @@ -0,0 +1,35 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://www.usenix.org/system/files/osdi20-rigger.pdf +TITLE: Incorrect result of LIKE. +DESCRIPTION: + https://www.usenix.org/system/files/osdi20-rigger.pdf + page 10 listing 5 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + create collation name_coll for utf8 from unicode case insensitive; + create domain dm_test varchar(2) character set utf8 collate name_coll; + + create table t0 (c0 dm_test unique); + insert into t0 (c0) values ( './'); + select * from t0 where c0 like './'; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 ./ + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 31823a1e2d2c821a1541cbe0b264ac95d298073f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:04 +0300 Subject: [PATCH 0534/1064] Added/Updated tests\functional\sqlancer\osdi20_rigger_example_12_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/osdi20_rigger_example_12_test.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/functional/sqlancer/osdi20_rigger_example_12_test.py diff --git a/tests/functional/sqlancer/osdi20_rigger_example_12_test.py b/tests/functional/sqlancer/osdi20_rigger_example_12_test.py new file mode 100644 index 00000000..bdc48c58 --- /dev/null +++ b/tests/functional/sqlancer/osdi20_rigger_example_12_test.py @@ -0,0 +1,48 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://www.usenix.org/system/files/osdi20-rigger.pdf +TITLE: Unexpected null value when index is used +DESCRIPTION: + https://www.usenix.org/system/files/osdi20-rigger.pdf + page 11 listing 12 +NOTES: + [05.06.2025] pzotov + page_size = 32K is used in this test. +""" + +import pytest +from firebird.qa import * + +db = db_factory(page_size = 32768) + +test_script = """ + set list on; + recreate table t0 (c0 varchar(8183)); + insert into t0 (c0) values('b'); + insert into t0 (c0) values('a'); + + insert into t0 (c0) values (null); + update t0 set c0 = 'a'; + commit; + + create index i0 on t0 (c0); + + set count on; + select * from t0 where 'baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' > t0.c0 ; -- error : found unexpected null value in index " i0 " + commit; +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=4.0') +def test_1(act: Action): + act.expected_stdout = """ + C0 a + C0 a + C0 a + Records affected: 3 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 7070f21cee3f37acb040994d251508981a4069b6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:09 +0300 Subject: [PATCH 0535/1064] Added/Updated tests\functional\sqlancer\tidb_15844_test.py: adapted from article provided in SQLancer documentation. --- tests/functional/sqlancer/tidb_15844_test.py | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/functional/sqlancer/tidb_15844_test.py diff --git a/tests/functional/sqlancer/tidb_15844_test.py b/tests/functional/sqlancer/tidb_15844_test.py new file mode 100644 index 00000000..80f1c289 --- /dev/null +++ b/tests/functional/sqlancer/tidb_15844_test.py @@ -0,0 +1,28 @@ +#coding:utf-8 + +""" +ID: 15844 +ISSUE: https://github.com/pingcap/tidb/issues/15844 +TITLE: NATURAL RIGHT JOIN results in an unexpected "Unknown column" error +DESCRIPTION: + https://github.com/sqlancer/sqlancer/blob/main/CONTRIBUTING.md#unfixed-bugs + https://github.com/sqlancer/sqlancer/blob/4c20a94b3ad2c037e1a66c0b637184f8c20faa7e/src/sqlancer/tidb/TiDBBugs.java +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + CREATE TABLE t0(c0 boolean); + CREATE TABLE t1(c0 boolean); + SELECT t0.c0 FROM t0 NATURAL RIGHT JOIN t1 WHERE t1.c0; -- Unknown column 't0.c0' in 'field list' +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From 0c69ca86b7ea92d9eb49c1b1b483f164f497ed2d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:14 +0300 Subject: [PATCH 0536/1064] Added/Updated tests\functional\sqlancer\tidb_16028_test.py: adapted from article provided in SQLancer documentation. --- tests/functional/sqlancer/tidb_16028_test.py | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/functional/sqlancer/tidb_16028_test.py diff --git a/tests/functional/sqlancer/tidb_16028_test.py b/tests/functional/sqlancer/tidb_16028_test.py new file mode 100644 index 00000000..26b572ef --- /dev/null +++ b/tests/functional/sqlancer/tidb_16028_test.py @@ -0,0 +1,28 @@ +#coding:utf-8 + +""" +ID: 16028 +ISSUE: https://github.com/pingcap/tidb/issues/16028 +TITLE: Incorrect result when comparing a FLOAT/DOUBLE UNSIGNED with a negative number +DESCRIPTION: + https://github.com/sqlancer/sqlancer/blob/main/CONTRIBUTING.md#unfixed-bugs + https://github.com/sqlancer/sqlancer/blob/4c20a94b3ad2c037e1a66c0b637184f8c20faa7e/src/sqlancer/tidb/TiDBBugs.java +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + CREATE TABLE t0(c0 double precision unique); + INSERT INTO t0(c0) VALUES (0); + SELECT * FROM t0 WHERE t0.c0 = -1; -- expected: {}, actual: {0} +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From 28a8a5ecd5c2eef14196be032146cdc068bfe574 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:20 +0300 Subject: [PATCH 0537/1064] Added/Updated tests\functional\sqlancer\tidb_35522_test.py: adapted from article provided in SQLancer documentation. --- tests/functional/sqlancer/tidb_35522_test.py | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/functional/sqlancer/tidb_35522_test.py diff --git a/tests/functional/sqlancer/tidb_35522_test.py b/tests/functional/sqlancer/tidb_35522_test.py new file mode 100644 index 00000000..3ca0b244 --- /dev/null +++ b/tests/functional/sqlancer/tidb_35522_test.py @@ -0,0 +1,28 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://github.com/pingcap/tidb/issues/35522 +TITLE: incorrect unresolved column when using natural join +DESCRIPTION: + https://github.com/sqlancer/sqlancer/blob/main/CONTRIBUTING.md#unfixed-bugs + https://github.com/sqlancer/sqlancer/blob/4c20a94b3ad2c037e1a66c0b637184f8c20faa7e/src/sqlancer/tidb/TiDBBugs.java +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + CREATE TABLE t0(c0 CHAR); + CREATE TABLE t1(c0 CHAR); + SELECT t1.c0 FROM t1 NATURAL RIGHT JOIN t0 WHERE true IS NULL; -- ERROR 1054 (42S22) at line 4: Unknown column 't1.c0' in 'field list' +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From a78e0786b4659f8ae7eb6ecc7e3e9c627fd5e2c1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:25 +0300 Subject: [PATCH 0538/1064] Added/Updated tests\functional\sqlancer\tidb_challenge_19_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/tidb_challenge_19_test.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/functional/sqlancer/tidb_challenge_19_test.py diff --git a/tests/functional/sqlancer/tidb_challenge_19_test.py b/tests/functional/sqlancer/tidb_challenge_19_test.py new file mode 100644 index 00000000..6c6af3ee --- /dev/null +++ b/tests/functional/sqlancer/tidb_challenge_19_test.py @@ -0,0 +1,31 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://github.com/tidb-challenge-program/bug-hunting-issue/issues/19 +TITLE: Incorrect result for LEFT JOIN and CASE operator +DESCRIPTION: + https://github.com/sqlancer/sqlancer/blob/main/CONTRIBUTING.md#unfixed-bugs + https://github.com/sqlancer/sqlancer/blob/4c20a94b3ad2c037e1a66c0b637184f8c20faa7e/src/sqlancer/tidb/TiDBBugs.java +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + CREATE TABLE t0(c0 INT); + CREATE TABLE t1(c0 INT); + INSERT INTO t0 VALUES (0); + INSERT INTO t1 VALUES (0); + SELECT * FROM t1 LEFT JOIN t0 ON t0.c0 = t1.c0 WHERE (CASE t0.c0 WHEN 0 THEN t1.c0 ELSE 1 END) <> 0; -- expected: {}, actual: {0|NULL} +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From 68efdbe36aadabb21c0e38bf639f3f86976457e4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 5 Jun 2025 11:36:30 +0300 Subject: [PATCH 0539/1064] Added/Updated tests\functional\sqlancer\tidb_challenge_48_test.py: adapted from article provided in SQLancer documentation. --- .../sqlancer/tidb_challenge_48_test.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/functional/sqlancer/tidb_challenge_48_test.py diff --git a/tests/functional/sqlancer/tidb_challenge_48_test.py b/tests/functional/sqlancer/tidb_challenge_48_test.py new file mode 100644 index 00000000..25888b99 --- /dev/null +++ b/tests/functional/sqlancer/tidb_challenge_48_test.py @@ -0,0 +1,29 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://github.com/tidb-challenge-program/bug-hunting-issue/issues/19 +TITLE: UNIQUE constraint on DECIMAL/floating-point columns causes incorrect result for NULL in AND +DESCRIPTION: + https://github.com/sqlancer/sqlancer/blob/main/CONTRIBUTING.md#unfixed-bugs + https://github.com/sqlancer/sqlancer/blob/4c20a94b3ad2c037e1a66c0b637184f8c20faa7e/src/sqlancer/tidb/TiDBBugs.java +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + CREATE TABLE t0(c0 DOUBLE PRECISION UNIQUE); + INSERT INTO t0(c0) VALUES (NULL); + SELECT t0.c0 FROM t0 WHERE NOT (t0.c0 is null AND true); -- expected: {}, actual: {NULL} +""" + +act = isql_act('db', test_script) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.execute(combine_output = True) + assert act.clean_stdout == '' From 6b53036fb22ed6bdcc12cc87f3af571747ba8376 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 7 Jun 2025 12:57:07 +0300 Subject: [PATCH 0540/1064] Added/Updated tests\functional\replication\test_uk_violation_in_rw_repl_if_constraint_name_is_used.py: Checked on 6.0.0.797-303e8d4. --- ...n_in_rw_repl_if_constraint_name_is_used.py | 541 ++++++++++++++++++ 1 file changed, 541 insertions(+) create mode 100644 tests/functional/replication/test_uk_violation_in_rw_repl_if_constraint_name_is_used.py diff --git a/tests/functional/replication/test_uk_violation_in_rw_repl_if_constraint_name_is_used.py b/tests/functional/replication/test_uk_violation_in_rw_repl_if_constraint_name_is_used.py new file mode 100644 index 00000000..86555f26 --- /dev/null +++ b/tests/functional/replication/test_uk_violation_in_rw_repl_if_constraint_name_is_used.py @@ -0,0 +1,541 @@ +#coding:utf-8 + +""" +ID: replication.test_uk_violation_in_rw_repl_if_constraint_name_is_used +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8139 +TITLE: PK/UK violation error raises in RW replica if constraint name is used to check uniqueness instead of index name +DESCRIPTION: + We create table with DDL described here: + https://github.com/FirebirdSQL/firebird/issues/8139#issuecomment-2940164974 + + Then we insert two records: first in REPLICA and after this in master, with same value of column 'ID1'. + After this we have to wait for seconds until record in replica will be updated + and have data that was used in master (i.e. data in replica must be overwritten). + + Message "WARNING: Record being inserted into table TEST already exists, updating instead" must appear + in the replication log at this point. + + Further, we invoke ISQL with executing auxiliary script for drop all DB objects on master (with '-nod' command switch). + After all objects will be dropped, we have to wait again until replica becomes actual with master. + Check that both DB have no custom objects is performed (see UNION-ed query to rdb$ tables + filtering on rdb$system_flag). + + Finally, we extract metadata for master and replica and make comparison. + The only difference in metadata must be 'CREATE DATABASE' statement with different DB names - we suppress it, + thus metadata difference must not be issued. + +NOTES: + [07.06.2025] pzotov + 1. We use 'assert' only at the final point of test, with printing detalization about encountered problem(s). + During all previous steps, we only store unexpected output to variables, e.g.: out_main = capsys.readouterr().out etc. + 2. Related tickets: + https://github.com/FirebirdSQL/firebird/issues/8040 + https://github.com/FirebirdSQL/firebird/issues/8042 + + Thanks to Vlad for explanation related to test implementation. + + Confirmed bug on 6.0.0.792-d90992f + Checked on 6.0.0.797-303e8d4. +""" +import os +import re +import shutil +from difflib import unified_diff +from pathlib import Path +import time + +import pytest +from firebird.qa import * +from firebird.driver import connect, create_database, DbWriteMode, ReplicaMode, ShutdownMode, ShutdownMethod, DatabaseError + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +repl_settings = QA_GLOBALS['replication'] + +MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG = int(repl_settings['max_time_for_wait_segment_in_log']) +MAX_TIME_FOR_WAIT_DATA_IN_REPLICA = int(repl_settings['max_time_for_wait_data_in_replica']) + +MAIN_DB_ALIAS = repl_settings['main_db_alias'] +REPL_DB_ALIAS = repl_settings['repl_db_alias'] +RUN_SWEEP_AT_END = int(repl_settings['run_sweep_at_end']) + +db_main = db_factory( filename = '#' + MAIN_DB_ALIAS, do_not_create = True, do_not_drop = True) +db_repl = db_factory( filename = '#' + REPL_DB_ALIAS, do_not_create = True, do_not_drop = True) + +substitutions = [('Start removing objects in:.*', 'Start removing objects'), + ('Finish. Total objects removed: [1-9]\\d*', 'Finish. Total objects removed'), + ('.* CREATE DATABASE .*', ''), + ('[\t ]+', ' '), + ('FOUND message about replicated segment N .*', 'FOUND message about replicated segment')] + +act_db_main = python_act('db_main', substitutions=substitutions) +act_db_repl = python_act('db_repl', substitutions=substitutions) +tmp_data = temp_file(filename = 'tmp_blob_for_replication.dat') + +#-------------------------------------------- + +def cleanup_folder(p): + # Removed all files and subdirs in the folder

+ # Used for cleanup and when replication must be reset + # in case when any error occurred during test execution. + assert os.path.dirname(p) != p, f"@@@ ABEND @@@ CAN NOT operate in the file system root directory. Check your code!" + + for root, dirs, files in os.walk(p): + for f in files: + # ::: NB ::: 22.12.2023. + # We have to expect that attempt to delete of GUID and (maybe) archived segments can FAIL with + # PermissionError: [WinError 32] The process cannot ... used by another process: /path/to/{GUID} + # Also, we have to skip exception if file (segment) was just deleted by engine + try: + Path(root +'/' + f).unlink(missing_ok = True) + except PermissionError as x: + pass + + for d in dirs: + shutil.rmtree(os.path.join(root, d), ignore_errors = True) + + return os.listdir(p) + +#-------------------------------------------- + +def reset_replication(act_db_main, act_db_repl, db_main_file, db_repl_file): + out_reset = '' + failed_shutdown_db_map = {} # K = 'db_main', 'db_repl'; V = error that occurred when we attempted to change DB state to full shutdown (if it occurred) + + with act_db_main.connect_server() as srv: + + # !! IT IS ASSUMED THAT REPLICATION FOLDERS ARE IN THE SAME DIR AS !! + # DO NOT use 'a.db.db_path' for ALIASED database! + # It will return '.' rather than full path+filename. + + repl_root_path = Path(db_main_file).parent + repl_jrn_sub_dir = repl_settings['journal_sub_dir'] + repl_arc_sub_dir = repl_settings['archive_sub_dir'] + + for f in (db_main_file, db_repl_file): + # Method db.drop() changes LINGER to 0, issues 'delete from mon$att' with suppressing exceptions + # and calls 'db.drop_database()' (also with suppressing exceptions). + # We change DB state to FULL SHUTDOWN instead of call action.db.drop() because + # this is more reliable (it kills all attachments in all known cases and does not use mon$ table) + # + try: + srv.database.shutdown(database = f, mode = ShutdownMode.FULL, method = ShutdownMethod.FORCED, timeout = 0) + + # REMOVE db file from disk: we can safely assume that this can be done because DB in full shutdown state. + ########################### + os.unlink(f) + except DatabaseError as e: + failed_shutdown_db_map[ f ] = e.__str__() + + + # Clean folders repl_journal and repl_archive: remove all files from there. + # NOTE: test must NOT raise unrecoverable error if some of files in these folders can not be deleted. + # Rather, this must be displayed as diff and test must be considered as just failed. + for p in (repl_jrn_sub_dir,repl_arc_sub_dir): + + remained_files = cleanup_folder(repl_root_path/p) + + if remained_files: + out_reset += '\n'.join( (f"Directory '{str(repl_root_path/p)}' remains non-empty. Could not delete file(s):", '\n'.join(remained_files)) ) + + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxx r e c r e a t e d b _ m a i n a n d d b _ r e p l xxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + for a in (act_db_main,act_db_repl): + d = a.db.db_path + failed_shutdown_msg = failed_shutdown_db_map.get( str(d), '' ) + if failed_shutdown_msg: + # we could NOT change state of this database to full shutdown --> we must NOT recreate it. + # Accumulate error messages in OUT arg (for displaying as diff): + # + out_reset += '\n'.join( failed_shutdown_msg ) + else: + try: + dbx = create_database(str(d), user = a.db.user) + dbx.close() + with a.connect_server() as srv: + srv.database.set_write_mode(database = d, mode = DbWriteMode.ASYNC) + srv.database.set_sweep_interval(database = d, interval = 0) + if a == act_db_repl: + srv.database.set_replica_mode(database = d, mode = ReplicaMode.READ_ONLY) + else: + with a.db.connect() as con: + con.execute_immediate('alter database enable publication') + con.execute_immediate('alter database include all to publication') + con.commit() + except DatabaseError as e: + out_reset += e.__str__() + + # Must remain EMPTY: + #################### + return out_reset + + +#-------------------------------------------- + +def wait_for_repl_err( act_db_main: Action, replold_lines, max_allowed_time_for_wait): + + replication_log = act_db_main.home_dir / 'replication.log' + + # ERROR: Database is not in the replica mode + p_warn_upd_instead_ins = re.compile('WARNING: .* already exists, updating instead', re.IGNORECASE) + + found_required_message = False + found_required_line = '' + for i in range(0,max_allowed_time_for_wait): + + time.sleep(1) + + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + + for k,d in enumerate(diff_data): + if p_warn_upd_instead_ins.search(d): + found_required_message = True + break + + if found_required_message: + break + + if not found_required_message: + # ACHTUNG! This looks weird but we have to either re-read replication log now or wait at least seconds + # if we want to see FULL (actual) content of this log! Otherwise last part of log will be missed. I have no explanations for that :( + with open(replication_log, 'r') as f: + diff_data = unified_diff( + replold_lines, + f.readlines() + ) + unexp_msg = f"Expected pattern '{p_warn_upd_instead_ins.pattern}' - was not found for {max_allowed_time_for_wait} seconds." + repllog_diff = '\n'.join( ( ('%4d ' %i) + r.rstrip() for i,r in enumerate(diff_data) ) ) + result = '\n'.join( (unexp_msg, 'Lines in replication.log:', repllog_diff) ) + else: + result = '' + + return result + +#-------------------------------------------- + +def watch_replica( a: Action, max_allowed_time_for_wait, ddl_ready_query = '', isql_check_script = '', replica_expected_out = ''): + + retcode = 1; + ready_to_check = False + if ddl_ready_query: + with a.db.connect(no_db_triggers = True) as con: + with con.cursor() as cur: + for i in range(0,max_allowed_time_for_wait): + cur.execute(ddl_ready_query) + count_actual = cur.fetchone() + if count_actual: + ready_to_check = True + break + else: + con.rollback() + time.sleep(1) + else: + ready_to_check = True + + if not ready_to_check: + print( f'UNEXPECTED. Initial check query did not return any rows for {max_allowed_time_for_wait} seconds.' ) + print('Initial check query:') + print(ddl_ready_query) + return + + final_check_pass = False + if isql_check_script: + retcode = 0 + for i in range(max_allowed_time_for_wait): + a.reset() + a.expected_stdout = replica_expected_out + a.isql(switches=['-q', '-nod'], input = isql_check_script, combine_output = True) + + if a.return_code: + # "Token unknown", "Name longer than database column size" etc: we have to + # immediately break from this loop because isql_check_script is incorrect! + break + + if a.clean_stdout == a.clean_expected_stdout: + final_check_pass = True + break + if i < max_allowed_time_for_wait-1: + time.sleep(1) + + if not final_check_pass: + print(f'UNEXPECTED. Final check query did not return expected dataset for {max_allowed_time_for_wait} seconds.') + print('Final check query:') + print(isql_check_script) + print('Expected output:') + print(a.clean_expected_stdout) + print('Actual output:') + print(a.clean_stdout) + print(f'ISQL return_code={a.return_code}') + print(f'Waited for {i} seconds') + + a.reset() + + else: + final_check_pass = True + + return + +#-------------------------------------------- + +def drop_db_objects(act_db_main: Action, act_db_repl: Action, capsys): + + # return initial state of master DB: + # remove all DB objects (tables, views, ...): + # + db_main_meta, db_repl_meta = '', '' + for a in (act_db_main,act_db_repl): + if a == act_db_main: + sql_clean = (a.files_dir / 'drop-all-db-objects.sql').read_text() + a.expected_stdout = """ + Start removing objects + Finish. Total objects removed + """ + a.isql(switches=['-q', '-nod'], input = sql_clean, combine_output = True) + + if a.clean_stdout == a.clean_expected_stdout: + a.reset() + else: + print(a.clean_expected_stdout) + a.reset() + break + + # NB: one need to remember that rdb$system_flag can be NOT ONLY 1 for system used objects! + # For example, it has value =3 for triggers that are created to provide CHECK-constraints, + # Custom DB objects always have rdb$system_flag = 0 (or null for some very old databases). + # We can be sure that there are no custom DB objects if following query result is NON empty: + # + ddl_ready_query = """ + select 1 + from rdb$database + where NOT exists ( + select custom_db_object_flag + from ( + select rt.rdb$system_flag as custom_db_object_flag from rdb$triggers rt + UNION ALL + select rt.rdb$system_flag from rdb$relations rt + UNION ALL + select rt.rdb$system_flag from rdb$functions rt + UNION ALL + select rt.rdb$system_flag from rdb$procedures rt + UNION ALL + select rt.rdb$system_flag from rdb$exceptions rt + UNION ALL + select rt.rdb$system_flag from rdb$fields rt + UNION ALL + select rt.rdb$system_flag from rdb$collations rt + UNION ALL + select rt.rdb$system_flag from rdb$generators rt + UNION ALL + select rt.rdb$system_flag from rdb$roles rt + UNION ALL + select rt.rdb$system_flag from rdb$auth_mapping rt + UNION ALL + select 1 from sec$users s + where upper(s.sec$user_name) <> 'SYSDBA' + ) t + where coalesce(t.custom_db_object_flag,0) = 0 + ) + """ + + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + + # Must be EMPTY: + print(capsys.readouterr().out) + + db_main_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + else: + db_repl_meta = a.extract_meta(charset = 'utf8', io_enc = 'utf8') + + + if RUN_SWEEP_AT_END: + # Following sweep was mandatory during 2021...2022. Problem was fixed: + # * for FB 4.x: 26-jan-2023, commit 2ed48a62c60c029cd8cb2b0c914f23e1cb56580a + # * for FB 5.x: 20-apr-2023, commit 5af209a952bd2ec3723d2c788f2defa6b740ff69 + # (log message: 'Avoid random generation of field IDs, respect the user-specified order instead'). + # Until this problem was solved, subsequent runs of this test caused to fail with: + # 'ERROR: Record format with length NN is not found for table TEST' + # + a.gfix(switches=['-sweep', a.db.dsn]) + + # Final point: metadata must become equal: + # + diff_meta = ''.join(unified_diff( \ + [x for x in db_main_meta.splitlines() if 'CREATE DATABASE' not in x], + [x for x in db_repl_meta.splitlines() if 'CREATE DATABASE' not in x]) + ) + # Must be EMPTY: + print(diff_meta) + +#-------------------------------------------- + +@pytest.mark.replication +@pytest.mark.version('>=6.0') +def test_1(act_db_main: Action, act_db_repl: Action, tmp_data: Path, capsys): + + out_prep = out_main = out_log = out_drop = '' + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + replication_log = act_db_main.home_dir / 'replication.log' + replold_lines = [] + with open(replication_log, 'r') as f: + replold_lines = f.readlines() + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # Obtain full path + filename for DB_MAIN and DB_REPL aliases. + # NOTE: we must NOT use 'a.db.db_path' for ALIASED databases! + # It will return '.' rather than full path+filename. + # Use only con.info.name for that! + # + db_info = {} + for a in (act_db_main, act_db_repl): + with a.db.connect(no_db_triggers = True) as con: + #if a == act_db_main and a.vars['server-arch'] == 'Classic' and os.name != 'nt': + # pytest.skip("Waiting for FIX: 'Engine is shutdown' in replication log for CS. Linux only.") + db_info[a, 'db_full_path'] = con.info.name + db_info[a, 'db_fw_initial'] = con.info.write_mode + + + with act_db_repl.connect_server() as srv: + srv.database.set_replica_mode(database = act_db_repl.db.db_path, mode = ReplicaMode.READ_WRITE) + + # Must be EMPTY: + out_prep = capsys.readouterr().out + if out_prep: + # Some problem raised during change DB header(s) + pass + else: + sql_init = ''' + set bail on; + recreate table test ( + id1 int constraint test_id2_unq unique using index test_id1_unq, + id2 int constraint test_id1_unq unique using index test_id2_unq, + name varchar(10) + ); + commit; + ''' + act_db_main.isql(switches=['-q'], input = sql_init, combine_output = True) + out_prep = act_db_main.clean_stdout + act_db_main.reset() + + if out_prep: + # Some problem raised during init_sql execution + pass + else: + # Query to be used for check that all DB objects present in replica (after last DML statement completed on master DB): + ddl_ready_query = "select 1 from rdb$relations where rdb$relation_name = upper('test')" + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, ddl_ready_query) + # Must be EMPTY: + out_prep = capsys.readouterr().out + + if out_prep: + # Some problem raised with delivering DDL changes to replica + pass + else: + blob_inserted_hashes = {} + + # NB: first we put data into REPLICA database! + ############################################## + for a in (act_db_repl, act_db_main): + with a.db.connect(no_db_triggers = True) as con: + cur = con.cursor() + dml = 'insert into test(id1, id2, name) values(?, ?, ?)' + if a == act_db_repl: + cur.execute(dml, (1, 2, '1-2')) + else: + # Put data in MASTER. Replication log must contain after this warning (and no errors). + # "WARNING: Record being inserted into table TEST already exists, updating instead" + # Before fix following messages started to appear in replication log: + # Database: + # ERROR: violation of PRIMARY or UNIQUE KEY constraint "TEST_ID2_UNQ" on table "TEST" + # Problematic key value is ("ID1" = 1) + # At segment 2, offset 48 + # + cur.execute(dml, (1, 3, '1-3')) + con.commit() + + # Must be EMPTY: + out_main = capsys.readouterr().out + + if out_main: + # Some problem raised with writing data into replica or master DB: + pass + else: + # No errors must be now. We have to wait now until data from MASTER be delivered to REPLICA + # Query to be used that replica DB contains all expected data (after last DML statement completed on master DB): + isql_check_script = """ + set bail on; + set blob all; + set list on; + set count on; + select + rdb$get_context('SYSTEM','REPLICA_MODE') replica_mode + ,id1 + ,id2 + from test; + """ + + isql_expected_out = f""" + REPLICA_MODE READ-WRITE + ID1 1 + ID2 3 + Records affected: 1 + """ + + ############################################################################## + ### W A I T U N T I L R E P L I C A B E C O M E S A C T U A L ### + ############################################################################## + watch_replica( act_db_repl, MAX_TIME_FOR_WAIT_DATA_IN_REPLICA, '', isql_check_script, isql_expected_out) + # Must be EMPTY: + out_main = capsys.readouterr().out + + ###################################################################### + ### W A I T F O R W A R N I N G I N R E P L . L O G ### + ###################################################################### + out_log = wait_for_repl_err( act_db_main, replold_lines, MAX_TIME_FOR_WAIT_SEGMENT_IN_LOG) + + drop_db_objects(act_db_main, act_db_repl, capsys) + + # Return replica mode to its 'normal' value: READ-ONLY: + with act_db_repl.connect_server() as srv: + srv.database.set_replica_mode(database = act_db_repl.db.db_path, mode = ReplicaMode.READ_ONLY) + + # Must be EMPTY: + out_drop = capsys.readouterr().out + + if [ x for x in (out_prep, out_main, out_log, out_drop) if x.strip() ]: + # We have a problem either with DDL/DML or with dropping DB objects. + # First, we have to RECREATE both master and slave databases + # (otherwise further execution of this test or other replication-related tests most likely will fail): + out_reset = reset_replication(act_db_main, act_db_repl, db_info[act_db_main,'db_full_path'], db_info[act_db_repl,'db_full_path']) + + # Next, we display out_main, out_drop and out_reset: + # + print('Problem(s) detected:') + if out_prep.strip(): + print('out_prep:') + print(out_prep) + if out_main.strip(): + print('out_main:') + print(out_main) + if out_log.strip(): + print('out_log:') + print(out_log) + if out_drop.strip(): + print('out_drop:') + print(out_drop) + if out_reset.strip(): + print('out_reset:') + print(out_reset) + + assert '' == capsys.readouterr().out From 8c2a11e0e542ede93c3a7aeacf88042b9013c1ef Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 7 Jun 2025 15:23:47 +0300 Subject: [PATCH 0541/1064] Added/Updated tests\bugs\gh_8589_test.py: Checked on 6.0.0.797-bc305e6; 5.0.3.1369-fe53465; 4.0.6.3206-9580691 --- tests/bugs/gh_8589_test.py | 83 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/bugs/gh_8589_test.py diff --git a/tests/bugs/gh_8589_test.py b/tests/bugs/gh_8589_test.py new file mode 100644 index 00000000..d4c8bdb9 --- /dev/null +++ b/tests/bugs/gh_8589_test.py @@ -0,0 +1,83 @@ +#coding:utf-8 + +""" +ID: issue-8589 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8589 +TITLE: PERCENT_RANK may return NaN instead of 0 +DESCRIPTION: +NOTES: + [07.06.2025] pzotov + Confirmed bug on 6.0.0.797-0-303e8d4 + Checked on 6.0.0.797-bc305e6; 5.0.3.1369-fe53465; 4.0.6.3206-9580691 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + + set list on; + recreate table test( + id integer not null, + the_int integer, + primary key (id) + ); + + insert into test(the_int, id) values (5, 1); + insert into test(the_int, id) values (6, 2); + insert into test(the_int, id) values (7, 3); + insert into test(the_int, id) values (13, 4); + insert into test(the_int, id) values (5, 5); + + select + id, + the_int, + row_number() over(partition by t.the_int order by t.id), + percent_rank() over(partition by t.the_int order by t.id), + cume_dist() over(partition by t.the_int order by t.id) + from test t + order by 1; +""" + +act = isql_act('db', test_script, substitutions = [('[\t ]+', ' ')]) + +expected_stdout = """ + ID 1 + THE_INT 5 + ROW_NUMBER 1 + PERCENT_RANK 0.000000000000000 + CUME_DIST 0.5000000000000000 + + ID 2 + THE_INT 6 + ROW_NUMBER 1 + PERCENT_RANK 0.000000000000000 + CUME_DIST 1.000000000000000 + + ID 3 + THE_INT 7 + ROW_NUMBER 1 + PERCENT_RANK 0.000000000000000 + CUME_DIST 1.000000000000000 + + ID 4 + THE_INT 13 + ROW_NUMBER 1 + PERCENT_RANK 0.000000000000000 + CUME_DIST 1.000000000000000 + + ID 5 + THE_INT 5 + ROW_NUMBER 2 + PERCENT_RANK 1.000000000000000 + CUME_DIST 1.000000000000000 +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From 2ac4a8d56ea2abb84460cb038c70ce3a66df7baf Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Sun, 8 Jun 2025 11:31:05 +0200 Subject: [PATCH 0542/1064] Fixed problem with utf8 db filenames in Database --- CHANGELOG.md | 6 ++++++ docs/changelog.txt | 5 +++++ src/firebird/qa/__about__.py | 2 +- src/firebird/qa/plugin.py | 6 +++--- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b27c9081..367c3221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.20.2] - 2025-06-08 + +### Fixed + +- Fixed problem with utf8 db filenames in `Database`. + ## [0.20.1] - 2025-04-29 ### Changed diff --git a/docs/changelog.txt b/docs/changelog.txt index 9104936f..4e2763bd 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -4,6 +4,11 @@ Changelog .. currentmodule:: firebird.qa.plugin +Version 0.20.2 +============== + +* Fixed problem with utf8 db filenames in `Database`. + Version 0.20.1 ============== diff --git a/src/firebird/qa/__about__.py b/src/firebird/qa/__about__.py index 40e23a9e..2ec32406 100644 --- a/src/firebird/qa/__about__.py +++ b/src/firebird/qa/__about__.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: 2021-present The Firebird Projects # # SPDX-License-Identifier: MIT -__version__ = "0.20.1" +__version__ = "0.20.2" diff --git a/src/firebird/qa/plugin.py b/src/firebird/qa/plugin.py index 74665cbb..cea31bf8 100644 --- a/src/firebird/qa/plugin.py +++ b/src/firebird/qa/plugin.py @@ -828,7 +828,7 @@ def drop(self) -> None: """ __tracebackhide__ = True - with connect_server(_vars_['server']) as srv: + with connect_server(_vars_['server'], encoding='utf8' if self.utf8filename else None) as srv: srv.database.no_linger(database=self.db_path) self._make_config() with connect(self.config_name) as db: @@ -881,12 +881,12 @@ def connect(self, *, user: Optional[str]=None, password: Optional[str]=None, def set_async_write(self) -> None: "Set the database to `async write` mode." __tracebackhide__ = True - with connect_server(_vars_['server']) as srv: + with connect_server(_vars_['server'], encoding='utf8' if self.utf8filename else None) as srv: srv.database.set_write_mode(database=self.db_path, mode=DbWriteMode.ASYNC) def set_sync_write(self) -> None: "Set the database to `sync write` mode." __tracebackhide__ = True - with connect_server(_vars_['server']) as srv: + with connect_server(_vars_['server'], encoding='utf8' if self.utf8filename else None) as srv: srv.database.set_write_mode(database=self.db_path, mode=DbWriteMode.SYNC) def existing_db_factory(*, filename: str='test.fdb', charset: Optional[str]=None, From 6a9ea69f9ecca6a5b161ff80aa3219efd21aa4d1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 9 Jun 2025 09:43:55 +0300 Subject: [PATCH 0543/1064] Added/Updated tests\functional\sqlancer\stonedb_misc_examples_test.py: Bugs Found in StoneDB by SQLancer - several examples, adjusted to FB syntax. --- .../sqlancer/stonedb_misc_examples_test.py | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 tests/functional/sqlancer/stonedb_misc_examples_test.py diff --git a/tests/functional/sqlancer/stonedb_misc_examples_test.py b/tests/functional/sqlancer/stonedb_misc_examples_test.py new file mode 100644 index 00000000..76ccef6a --- /dev/null +++ b/tests/functional/sqlancer/stonedb_misc_examples_test.py @@ -0,0 +1,131 @@ +#coding:utf-8 + +""" +ID: n/a +ISSUE: https://docs.google.com/document/d/1N-oUGVATV0l6tG87uOtPNmfLS7g_fuo7HIckFobD-Yo/edit?tab=t.0 +TITLE: Bugs Found in StoneDB by SQLancer +DESCRIPTION: + This test contains several tiny examples provided in "GSoC 2023: Midterm Report on Support of StoneDB" +NOTES: + See also: + https://sqlancer.github.io/blog/gsoc-sqlancer-midterm-zhenglin/ +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + -- https://github.com/stoneatom/stonedb/issues/1941 + -- StoneDB will crash when executing the command: + set heading off; + select 'stonedb_1941' as msg from rdb$database; + recreate table t0 (c0 int); + SELECT * + FROM t0 + GROUP BY t0.c0 + HAVING (t0.c0 IS NULL) + UNION ALL + SELECT * + FROM t0 + GROUP BY t0.c0 + HAVING (NOT (t0.c0 IS NULL)) + UNION ALL + SELECT * + FROM t0 + GROUP BY t0.c0 + HAVING (((t0.c0 IS NULL)) IS NULL); + commit; + --################################################### + -- https://github.com/stoneatom/stonedb/issues/1952 + -- StoneDB crash: PRIMARY KEY, HAVING, IS NULL + select 'stonedb_1952' as msg from rdb$database; + RECREATE TABLE t0(c0 INT PRIMARY KEY); + -- NB: mysql *allows* such query and issues empty resultset. + -- FB raises "Invalid expression in the select list": + SELECT * FROM t0 HAVING (t0.c0 IS NULL); + commit; + --################################################### + -- https://github.com/stoneatom/stonedb/issues/1954 + -- StoneDB crash: HAVING, IS NULL + select 'stonedb_1954' as msg from rdb$database; + RECREATE TABLE t0(c0 INT PRIMARY KEY); + -- NB: mysql *allows* such query and issues empty resultset. + -- FB raises "Invalid expression in the select list": + SELECT c0 FROM t0 HAVING (1 IS NULL); + commit; + + --################################################### + -- https://github.com/stoneatom/stonedb/issues/1949 + -- StoneDB crash: HAVING, IS NULL + select 'stonedb_1949' as msg from rdb$database; + RECREATE TABLE t0(c0 blob); + INSERT INTO t0 DEFAULT values; + DELETE FROM t0; + INSERT INTO t0 DEFAULT values; + SELECT * FROM t0; + commit; + --################################################### + -- https://github.com/stoneatom/stonedb/issues/1950 + -- query result wrong: CASE WHEN THEN ELSE + select 'stonedb_1950' as msg from rdb$database; + RECREATE TABLE t0(c0 INT); + INSERT INTO t0 default values; + SELECT * FROM t0 WHERE (CASE (t0.c0 IN (t0.c0)) WHEN TRUE THEN 'TRUE' ELSE 'FALSE' END) = true; + commit; + --################################################### + -- https://github.com/stoneatom/stonedb/issues/1955 + -- query result wrong: ALTER, DEFAULT + select 'stonedb_1955' as msg from rdb$database; + RECREATE TABLE t0(c0 INT) ; + INSERT INTO t0 DEFAULT VALUES; + COMMIT; + ALTER TABLE t0 ADD c1 INT DEFAULT 1; + INSERT INTO t0 DEFAULT VALUES; + SELECT * FROM t0 order by c0,c1 nulls first; + commit; + + --################################################### + -- https://docs.google.com/document/d/1N-oUGVATV0l6tG87uOtPNmfLS7g_fuo7HIckFobD-Yo/edit?tab=t.0 + -- BUGS OR CRASHES FOUND BUT NOT REPORTED + -- query result wrong: >=, IS NULL + -- expected empty set: + select 'stonedb_non_reported_01' as msg from rdb$database; + RECREATE TABLE t0(c0 INT) ; + INSERT INTO t0 default VALUES; + SELECT t0.c0 FROM t0 WHERE (('false')>=(((t0.c0) IS NULL))); +""" + +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = """ + stonedb_1941 + + stonedb_1952 + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) + + stonedb_1954 + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) + + stonedb_1949 + + + stonedb_1950 + + stonedb_1955 + + 1 + + stonedb_non_reported_01 + """ + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From ae5825a1bfac681a244dd5f1ab7bdf3a90ad046c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 10 Jun 2025 15:16:06 +0300 Subject: [PATCH 0544/1064] Added/Updated tests\bugs\gh_8592_test.py: Checked on 6.0.0.799-c82c9cf; 5.0.3.1660-0-d0d870a; 4.0.6.3207-4a300e7 --- tests/bugs/gh_8592_test.py | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/bugs/gh_8592_test.py diff --git a/tests/bugs/gh_8592_test.py b/tests/bugs/gh_8592_test.py new file mode 100644 index 00000000..fbc68b9f --- /dev/null +++ b/tests/bugs/gh_8592_test.py @@ -0,0 +1,40 @@ +#coding:utf-8 + +""" +ID: issue-8592 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8592 +TITLE: Presence of 'ROWS ' causes garbage in error message when string conversion problem raises +DESCRIPTION: + See https://www.sqlite.org/src/tktview/de7db14784 +NOTES: + [10.06.2025] pzotov + Checked on 6.0.0.799-c82c9cf; 5.0.3.1660-0-d0d870a; 4.0.6.3207-4a300e7 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set heading off; + create table test_a(f01 varchar(5) primary key, f02 varchar(5)); + create table test_b(f01 varchar(5), f02 int); + insert into test_a values('one', 'i'); + insert into test_b values('one', 1); + select a.f01 from test_a a where exists (select 1 from test_b b where a.f01 = b.f02 rows 1); +""" + +act = isql_act('db', test_script, substitutions = [('[\t ]+', ' ')]) + +expected_stdout = """ + Statement failed, SQLSTATE = 22018 + conversion error from string "one" +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From 69ef7aebfbdd2b3944bc51a94ddab9665397ee2f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 12 Jun 2025 12:28:05 +0300 Subject: [PATCH 0545/1064] Added/Updated tests\bugs\gh_8579_test.py: Checked on 6.0.0.800-96dd669e --- tests/bugs/gh_8579_test.py | 153 ++++++++++++++++++++++++++++++------- 1 file changed, 124 insertions(+), 29 deletions(-) diff --git a/tests/bugs/gh_8579_test.py b/tests/bugs/gh_8579_test.py index e5f9c702..9fc7a450 100644 --- a/tests/bugs/gh_8579_test.py +++ b/tests/bugs/gh_8579_test.py @@ -7,71 +7,166 @@ DESCRIPTION: Test creates procedure (sp_main) and function (fn_main) and each contains declarations of inner procedures and functions. - Then we run query 'select rdb$debug_info from rdb$...' and check that line line 'BLR to Source mapping:' - occurs exactly times for each kind sub-routine. + Also, package with two units is created: procedure 'packaged_proc' and function 'packaged_func', and each + of them have declarations of inner sub-units (procedures and functions). + Then we run query 'select rdb$debug_info from rdb$...' and check that line line + occurs: + * one time for each 'main-level' unit (i.e. sp_main; fn_pain; packaged_proc and packaged_func; + * exactly times after each kind sub-routine name. + Expected output is build 'on-the-fly' during generation of appropriate DDL expressions, see 'expected_lst'. + One need to keep in mind that rdb$debug_info shows inner functions *before* inner procedures. NOTES: [31.05.2025] pzotov If we try to declare inner procedures 19 times then line 'BLR to Source mapping:' appears to be "broken" for last (19th) sub-routine. Because of this, test currently must use no more than 18 declarations. - Sent report to Adriano, waiting for fix. + See: https://github.com/FirebirdSQL/firebird/issues/8590 - Checked on 6.0.0.792-d90992f. + Problem did exist up to 6.0.0.799-c82c9cf and has been fixed 11-jun-2025: + https://github.com/FirebirdSQL/firebird/commit/c867f34da84fbc0e1843757c386f955c014d8d41 + After fix, test execution time is ~6s. + + Checked on 6.0.0.800-96dd669e """ import pytest from firebird.qa import * +import time -SUBROUTINES_COUNT = 18 # 31.05.2025: 19 - broken line 'BLR to Source mapping:' ! +SUBROUTINES_COUNT = 2000 # 31.05.2025: 19 - broken line 'BLR to Source mapping:', see #8590. BLR_TO_SOURCE_TXT = 'BLR to Source mapping:' -substitutions = [ ('^((?!' + BLR_TO_SOURCE_TXT + '|Sub function|Sub procedure).)*$', '') ] db = db_factory() +substitutions = [ ('^((?!' + BLR_TO_SOURCE_TXT + '|Sub function|Sub procedure).)*$', '') ] act = python_act('db', substitutions = substitutions) expected_lst = [] -proc_ddl = [ 'create procedure sp_main as' ] +ddl_sp = [] +ddl_fn = [] +ddl_pkg = [] +ddl_pbd = [] + +# ................................................... +# ... f u n c t i o n, s t a n d a l o n e ... +# ................................................... +expected_lst.append(BLR_TO_SOURCE_TXT) +ddl_fn = [ 'create function fn_main returns int as' ] for i in range(SUBROUTINES_COUNT): - proc_ddl.extend( [f' declare function sp_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) - expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub function SP_MAIN_SUB_FUNC_{i:05}:']) + # Inner functions: + ddl_fn.extend( [f' declare function fn_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) for i in range(SUBROUTINES_COUNT): - proc_ddl.extend( [f' declare procedure sp_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) - expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub procedure SP_MAIN_SUB_PROC_{i:05}:']) -proc_ddl.extend( ['begin', 'end'] ) + # Inner procedures: + ddl_fn.extend( [f' declare procedure fn_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) +ddl_fn.extend( ['begin', ' return 1;', 'end'] ) -expected_lst.append(BLR_TO_SOURCE_TXT) +# Add lines that must be in expected output. NOTE: inner functions are shown always BEFORE procedures! +for suffix in ('sub_func', 'sub_proc'): + sub_routine_type = 'function' if suffix == 'sub_func' else 'procedure' + for i in range(SUBROUTINES_COUNT): + expected_lst.extend([f'Sub {sub_routine_type} FN_MAIN_{suffix.upper()}_{i:05}:', BLR_TO_SOURCE_TXT]) -#.......................................................................................... -func_ddl = [ 'create function fn_main returns int as' ] +# ..................................................... +# ... p r o c e d u r e, s t a n d a l o n e ... +# ..................................................... +expected_lst.append(BLR_TO_SOURCE_TXT) +ddl_sp = [ 'create procedure sp_main as' ] for i in range(SUBROUTINES_COUNT): - func_ddl.extend( [f' declare function fn_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) - expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub function FN_MAIN_SUB_FUNC_{i:05}:']) + # Inner functions: + ddl_sp.extend( [f' declare function sp_main_sub_func_{i:05} returns int as', ' begin', f' return {i};', ' end'] ) for i in range(SUBROUTINES_COUNT): - func_ddl.extend( [f' declare procedure fn_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) - expected_lst.extend([BLR_TO_SOURCE_TXT, f'Sub procedure FN_MAIN_SUB_PROC_{i:05}:']) -func_ddl.extend( ['begin', ' return 1;', 'end'] ) + # Inner procedures: + ddl_sp.extend( [f' declare procedure sp_main_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = {i};', ' end'] ) +ddl_sp.extend( ['begin', 'end'] ) + +# Add lines that must be in expected output. NOTE: inner functions are shown always BEFORE procedures! +for suffix in ('sub_func', 'sub_proc'): + sub_routine_type = 'function' if suffix == 'sub_func' else 'procedure' + for i in range(SUBROUTINES_COUNT): + expected_lst.extend([f'Sub {sub_routine_type} SP_MAIN_{suffix.upper()}_{i:05}:', BLR_TO_SOURCE_TXT]) + + +# ............................................................. +# ... p a c k a g e w i t h f u n c a n d p r o c +# ............................................................. +ddl_pkg = [ 'create package pg_test as', 'begin' ] +ddl_pkg.extend( [' function packaged_func returns int;'] ) +ddl_pkg.extend( [' procedure packaged_proc;'] ) +ddl_pkg.extend( ['end'] ) # end of package header + +ddl_pbd = [ 'create package body pg_test as', 'begin' ] + +# packaged function with inner units: +# ------------------------------------------------------- +ddl_pbd.extend( [' function packaged_func returns int as' ] ) +for i in range(SUBROUTINES_COUNT): + ddl_pbd.extend( [f' declare function pg_func_sub_func_{i:05} returns int as', ' begin', f' return 1;', ' end'] ) + ddl_pbd.extend( [f' declare procedure pg_func_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = 1;', ' end'] ) +ddl_pbd.extend( [' begin', ' end'] ) -expected_lst.append(BLR_TO_SOURCE_TXT) -#----------------------------------------------------------------------------------------- +# packaged procedure with inner units: +# -------------------------------------------------------- +ddl_pbd.extend( [' procedure packaged_proc as' ] ) +for i in range(SUBROUTINES_COUNT): + ddl_pbd.extend( [f' declare function pg_proc_sub_func_{i:05} returns int as', ' begin', f' return 1;', ' end'] ) + ddl_pbd.extend( [f' declare procedure pg_proc_sub_proc_{i:05} as', ' declare n int;', ' begin', f' n = 1;', ' end'] ) + +ddl_pbd.extend( [' begin', ' end'] ) + +ddl_pbd.extend( ['end'] ) # end of package body + +# Add lines that must be in expected output. NOTE: inner functions are shown always BEFORE procedures! +for prefix in ('pg_func', 'pg_proc'): + expected_lst.append(BLR_TO_SOURCE_TXT) + for i in range(SUBROUTINES_COUNT): + expected_lst.extend([f'Sub function {prefix.upper()}_SUB_FUNC_{i:05}:', BLR_TO_SOURCE_TXT]) + + for i in range(SUBROUTINES_COUNT): + expected_lst.extend([f'Sub procedure {prefix.upper()}_SUB_PROC_{i:05}:', BLR_TO_SOURCE_TXT]) + +##################################################################################################### @pytest.mark.version('>=6.0') def test_1(act: Action, capsys): with act.db.connect(charset = 'utf8') as con: - con.execute_immediate('\n'.join([x.strip() for x in proc_ddl])) - con.execute_immediate('\n'.join([x.strip() for x in func_ddl])) - con.commit() + + for ddl_cmd_lst in (ddl_sp, ddl_fn, ddl_pkg, ddl_pbd): + if ddl_cmd_lst: + ddl_cmd_txt = '\n'.join([x.strip() for x in ddl_cmd_lst]) + #print(len(ddl_cmd_txt)) + con.execute_immediate( ddl_cmd_txt ) + con.commit() - sources_map = { 'rdb$procedures' : ('rdb$procedure_name', 'sp_main'), 'rdb$functions' : ('rdb$function_name', 'fn_main') } - for k,v in sources_map.items(): - check_sql = f"set heading off; set blob all; select p.rdb$debug_info as blob_debug_info from {k} p where p.{v[0]} = upper('{v[1]}');" + rdb_query_data = ( + ('rdb$functions', 'rdb$function_name', 'fn_main', None) + ,('rdb$procedures', 'rdb$procedure_name', 'sp_main', None) + ,('rdb$functions', 'rdb$function_name', 'packaged_func', 'pg_test') + ,('rdb$procedures', 'rdb$procedure_name', 'packaged_proc', 'pg_test') + ) + + for p in rdb_query_data: + + rdb_table_name, rdb_field_name, rdb_field_value, rdb_package_name = p + + check_sql = f""" + set heading off; + set blob all; + select p.rdb$debug_info as blob_debug_info + from {rdb_table_name} p + where p.{rdb_field_name} = '{rdb_field_value.upper()}' + """ + if rdb_package_name: + check_sql += f" and p.rdb$package_name = '{rdb_package_name.upper()}';" + else: + check_sql += f" and p.rdb$package_name is null;" + act.isql(switches = ['-q'], input = check_sql, combine_output = True) print(act.stdout) act.reset() - + act.expected_stdout = '\n'.join(expected_lst) act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 1bb848cd5bf0c560c09d178c9a8cb962e1b27c17 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 13:03:41 +0300 Subject: [PATCH 0546/1064] Added .zip that is needed for gh_8595_test.py --- files/gh_8595-ods13_1.zip | Bin 0 -> 578 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_8595-ods13_1.zip diff --git a/files/gh_8595-ods13_1.zip b/files/gh_8595-ods13_1.zip new file mode 100644 index 0000000000000000000000000000000000000000..1ae41e8637ffc2662e12a218d4eddd2287cb35a5 GIT binary patch literal 578 zcmWIWW@Zs#U|`^2couawN@m;Vo6{J9TowifVIY;B5pQ8?X{wu_Qfz1(Z>X1+lzny5 zN&iC*BFFAenYgVXqk}u{%#kk-+BWKl=cN`pYD^3h78VNf;#AwBT4M2g`Qs8R84r`T z#kMuZ`JbxqM+Z$P5MwZK^ZCAGnPIo%!}6asa=Xseh`DXqw}yY^bN#j}@gXb4FYbPs z($mF%+W%4{tIK+U*!9!3OJmia{x0JER5|C-Jcovzg2D>NZ7<5tYe>0S^)~Bjlxp|c zeK+l#3eE_rZZXd=HHkgg&M@I1SFosYqt11veVwoG)|dv`Uv-(=9C!Z;&uz0={(HA& zMqj$s5_hLztKOz_UU#Eo5-!fv2-9A=mVfnC1BKR0@0EAw-W0OylARf@x9*Nn&f>&~ z+%50qK6#2vj5_;RT+Hp>onp_N{FRRC zeaZ9Z@q6h2Z$>7223!%T0*p!!P*4C<*rJt-0V2o9Ai=PA=94s=JGU95wg&Us0qNZH Z74NKpbbvQ28^{1gAWQ|)$3ZED0RSp}=tBSi literal 0 HcmV?d00001 From fb3fb643ba6aa4547ac3c70d1aae4e8e4cb09e9a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 13:04:12 +0300 Subject: [PATCH 0547/1064] Added/Updated tests\bugs\gh_8595_test.py: Checked on 6.0.0.834-a9a0f28. --- tests/bugs/gh_8595_test.py | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tests/bugs/gh_8595_test.py diff --git a/tests/bugs/gh_8595_test.py b/tests/bugs/gh_8595_test.py new file mode 100644 index 00000000..687eb1ca --- /dev/null +++ b/tests/bugs/gh_8595_test.py @@ -0,0 +1,66 @@ +#coding:utf-8 + +""" +ID: issue-8595 +ISSUE: 8595 +TITLE: Unable to restore database to Firebird 6.0 (with schemas) from ODS 13.1 if database contains views with system tables used in subqueries +DESCRIPTION: + Test uses backup of database that was created in ODS 13.1 (FB 5.0.3.x) and contain view V_TEST with column defined as subquery to mon$attachments table: + create view v_test as + select (select count(*) from mon$attachments) as att_cnt + from rdb$database; + We extract this .fbk from .zip and try to restore from it using services API. No errors must occur + Finally, we run query to the V_TEST. It must run w/o errors and return one row. +NOTES: + [13.06.2025] pzotov + Confirmed bug on 6.0.0.800 (got 'table "PUBLIC"."MON$ATTACHMENTS" is not defined'). + Checked on 6.0.0.834-a9a0f28. +""" + +import pytest +import zipfile +import locale +from pathlib import Path +from firebird.qa import * +from firebird.driver import SrvRestoreFlag, DatabaseError +import time + +db = db_factory() + +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +tmp_fbk = temp_file('gh_8595-ods13_1.fbk') +tmp_fdb = temp_file('tmp_restore_8595.fdb') + +#------------------------------------------------------------------ +# Callback function: capture output of ERROR messages in restore (output must be empty): +def print_log(line: str) -> None: + if ( s:= line.strip()): + if 'ERROR' in s: + print(s) +#------------------------------------------------------------------ + +@pytest.mark.version('>=6.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_8595-ods13_1.zip', at = 'gh_8595-ods13_1.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + # + restore_log = [] + with act.connect_server(encoding_errors = locale.getpreferredencoding()) as srv: + try: + srv.database.restore(backup=tmp_fbk, database=tmp_fdb, flags=SrvRestoreFlag.REPLACE, verbose=True, callback = print_log) + act.isql( switches=[ str(tmp_fdb), '-q' ], connect_db = False, input = 'set list on; select sign(att_cnt) as att_cnt_sign from v_test;', combine_output = True ) + print(act.stdout) + except DatabaseError as e: + print(f'Restore failed:') + print(e.__str__()) + print(e.gds_codes) + except Exception as x: + print(x) + + act.expected_stdout = """ + ATT_CNT_SIGN 1 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 2bbf6a819e61b5b602766cfc4282ba6164f02bf8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 15:48:38 +0300 Subject: [PATCH 0548/1064] Added/Updated tests\bugs\core_0058_test.py: Increased the 'subsitutions' list to suppress PUBLIC schema prefix and remove single/double quotes from object names. Need since 6.0.0.834. SEE NOTES. --- tests/bugs/core_0058_test.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_0058_test.py b/tests/bugs/core_0058_test.py index 69ddc6d2..f4dbe7e8 100644 --- a/tests/bugs/core_0058_test.py +++ b/tests/bugs/core_0058_test.py @@ -5,15 +5,27 @@ ISSUE: 383 TITLE: WHERE CURRENT OF doesn't work DESCRIPTION: -JIRA: CORE-58 -FBTEST: bugs.core_0058 +NOTES: + [13.06.2025] pzotov + 1. Increased the 'subsitutions' list to suppress "PUBLIC" schema prefix and remove single/double quotes from object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (thi file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Checked on 6.0.0.835; 5.0.3.1661; 4.0.6.3207; 3.0.13.33807. """ import pytest from firebird.qa import * -substitutions = [('line: [0-9]+, col: [0-9]+', '')] - db = db_factory() test_script = """ @@ -49,12 +61,22 @@ execute procedure test_upd (2); """ +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + act = isql_act('db', test_script, substitutions=substitutions) expected_stderr = """ Statement failed, SQLSTATE = 22000 no current record for fetch operation - -At procedure 'TEST_UPD' + -At procedure TEST_UPD """ @pytest.mark.version('>=3') From da26f4d402512f4d34e2803452035092657b45b7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 15:57:57 +0300 Subject: [PATCH 0549/1064] Added section 'schema_n_quotes_suppress', see notes to lot of tests related to schemas introducing, since 6.0.0.834 --- files/test_config.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/files/test_config.ini b/files/test_config.ini index 11d44ebf..75519ebd 100644 --- a/files/test_config.ini +++ b/files/test_config.ini @@ -86,3 +86,6 @@ ARCHIVE_SUB_DIR = repl_archive # related to record format) set RUN_SWEEP_AT_END to 1. # RUN_SWEEP_AT_END = 0 + +[schema_n_quotes_suppress] +addi_subst="PUBLIC". " ' From cc2deee37bd28381333f27ac4ea9f13f86547fbf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 22:47:48 +0300 Subject: [PATCH 0550/1064] Added file that is needed for test gh_8597 --- files/gh_8597-ods13_1.zip | Bin 0 -> 984 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/gh_8597-ods13_1.zip diff --git a/files/gh_8597-ods13_1.zip b/files/gh_8597-ods13_1.zip new file mode 100644 index 0000000000000000000000000000000000000000..4e2e6ce98d315b599cbb47a812686e0339789575 GIT binary patch literal 984 zcmWIWW@Zs#U|`^2u-J4qs?1t#wGK0o%frAR45ZRC;w?-q&2{rriVcn94fWEJvhRk) z=L`y_wi(Tvq;@~d*?b99!PE&Rx+GefE+s-u3AT8q8=(F3wOt>tQr)$D$8 z{&M}pRHt`GR;=i{^Tw+ty|drkId|^E?VUf*>ab5~Wo$51dct(dRjq{MQB?H>BVq^umMXWtCQQ@7_G0_O0@lXBB^vp_qfu z1BD9}k_t^TQux#ad{^(&Tbur^?C_cxP4O^}B^(ZOGL9DQ4O?+7rG-g&DO+Hf-uZ<* z8cP(aie|*yYfdTJy4Y*ytb**XMejl#ncbKssGPp^DQ3qNzasaivo>W4FiJJV-`LMQ zN4+7)E2vN)SyaJIL$F_$$su7%%S4HLdjmC(y<>6+wtp?9sMogC+WGVYX=!%FyBW?h zn>QWVi4UMYw{#7Z*CHrwruC( z9fA%g1N0WiJP&b}ocZ+=r@he3ZjrF{LLY@E9+}ZlOrirAhjspMwA0ogJ=H%eUI_XsoZ6kh#V)>FuAwHd)O+GeKQ`x?p}mgOmbUIsD#;0?@=Vo_jgDClx7GYsc?^XQxF zir?AZ^SZuFKmPy7cpT%1I&3I)s#kacklw0-w!w(k#RBgHwJL?6BT-I%)V%eM=c zem+=}$N%aRbK>SebE(?7*7Mn{%&qsNerv03j(+=W*V6A&e%DRjB?Hd@iw==kxhK=|YLhn=6NozHpn?8hwb4c~mv^5oy(FyuT} zp16BmPRLQElD(Z@T3`I-nC+(e?1^*4-J|~Eq0NVK7lnn`GC#R{B>Zlm6!)XID!)H% z|95oLaeKSt@mt!D+iU)H{*ZsnKfs%j$({jM_EG_6Fc44xlUOqw7gUmwL4rZD_UVo3 jcWyJ Date: Fri, 13 Jun 2025 23:05:29 +0300 Subject: [PATCH 0551/1064] Updated DDL and recreate .fbk for test gh_8597 --- files/gh_8597-ods13_1.zip | Bin 984 -> 1017 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/files/gh_8597-ods13_1.zip b/files/gh_8597-ods13_1.zip index 4e2e6ce98d315b599cbb47a812686e0339789575..ea3e32b91f36fd0466e64f7fba1303def1502e9b 100644 GIT binary patch delta 983 zcmV;|11S912l)qoP)h>@6aWAK2mnI2%~~;}96n700000E000vJ003ubUpO^6H!W{u zb1^etF)n6eYwcFuP7^^CKC>OVwZF7bqu|e6pumL$3N@ynNs*Rda6#G&O-P!h-D0)f z-Ry2JyffVU1iXXs(iiZ#>dfgByKJ>0iD2R+dv?yw={Ki;=ljm=fa^AIAW49m_Ssu@@jW(Ex#J0+MZULCXginDWaCOTD4TEiVQg>S``xX zi`Yk@pg1V76|}>UIu!6_@DK5lXM9H zj*R1$8D)GphSzmWHa`+`em!cK4M<`ACTW3NqENwqRS^@z=ZeCOn7k7X)}CMOVW-2d zURqW+p9xpqRJJyYQ&`Apv@m&AW!wNlXertWv|+R=+W4q4rGrRhEK*GVm3WY{H2ypj zT$u8c4e3-&-QUJ7Nt91U$|a8X1pRy^qM3pXTd%*@kBvs{qLLXye-cTS^ryr>mh?+U z(m$Gi^=P1QmsLOz^>3?TmZ+6|-s7NOrRDw054 z$``k@btadwk>t^gln%*8u(7$X_(VanDz~?Z0=-kAn7|_7BG=9h+4O5sNq-EB5l5S# z|Hg_&n6z*-4)wgYvjmoGX{({Ew*)BcYON0jLhBj-Vr{?sxh1Cj2285U$YsWVr8b z$Eq8Ru46F!xaQh5@%gc!*G#=*Fzw?vXkK^kuyc!L*(@!Rvu<5 zjo>jR8u*v-Wz83#8W+F6?TgQd_$d4zAOH0D4p2)00zUv00000807AFTS}~*?K1~Av z000h?cLOsnU$I@6aWAK2mm;;&02OlCaWw10000C000vJ003ubUpO^6H!W{u zb1^etF)n6eYu#2~ZxTTepIx>+x0=+|JJM+qwCF%`69$g#myuBIE+fMJ99z z;#zyqGh2<`2h(=4R`%4<`-4-bKgc+`?QD12O>(Dbb@|Jo!FP6fI-T9w&t~>{`bl~Z zVlfs#OyD5Uco`sqm}Cwn5KXJTF0E(wcEhY(DHm1HGb(1!t@OnlB~;FT_L7U$_tnFEZW+_Ff)bXdxudud zK*>-ppd9B^Lm8R%@(Di@nTr%wuM+VSk-(oP{f1>Pg^-Acwc{6fBngSd%p!>3Gs?bR zp%jABk}p;AQ~uqXS0sH7t1-o0O)3&MDCQft@>a4so6L|WAD1C^`c{dVP}j}u8quo9 zo+Al=9`Ml9FJ`^l=Fj-f0c!Tp9*DLX_fC-gxGdp5zqrTm=x|yEb3Mu9RaG1$6$COa z4(h1{lG22{ODK%aWtsSlFgA`#w^RdXLW=V+CL@9}%8Ik59;y*VY5*;8hxER zp9VTNJG^D~hJAxu?dH0r_Zm*uH0*7+hVEOg|6QAJ;)U|Z2*P>%`va7nq0y4tGN_J! zfkE-j5Le^x!$aq0&urr6_?io__D#(UZ`cSi3C?$6yRK|h#UgaQiS&i&{Ro>zCFbNq zSlz`>7gdA8ZK76GJp<(3#8=%>8Vlm>B>VEW{>8G#KR(A_w1>w(Dg8t6Z^lnhO928u z02BZK00;m$vdvm{J0`0v0{{R33;+O=ngcN|8GYs0m)zR{JQVTSo7~$0=9=Kxm)zR{ ZP)h{{000000RRC2WdHyGT>}6B002V@vjG4A From 7f62b488c179ca0c3a72f780d1bd0a9571235b61 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 13 Jun 2025 23:05:51 +0300 Subject: [PATCH 0552/1064] Added/Updated tests\bugs\gh_8597_test.py: Confirmed bug on 6.0.0.835-3da8317. Checked on 6.0.0.835-0-b1fd7d8. --- tests/bugs/gh_8597_test.py | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/bugs/gh_8597_test.py diff --git a/tests/bugs/gh_8597_test.py b/tests/bugs/gh_8597_test.py new file mode 100644 index 00000000..191b0217 --- /dev/null +++ b/tests/bugs/gh_8597_test.py @@ -0,0 +1,80 @@ +#coding:utf-8 + +""" +ID: issue-8597 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8597 +TITLE: Unable to restore database to Firebird 6.0 (with schemas) from ODS 13.1 if database contains views with system tables used in subqueries +DESCRIPTION: + Test uses backup of database that was created in ODS 13.1 (FB 5.0.3.x) and contains + * standalone procedure + function + * package with procedure and function. + Every unit has IN-parameters defined as type of columns from some rdb$tables, and OUT parameters referencing to rdb$ domains. + We extract this .fbk from .zip and try to restore from it using services API. No errors must occur + Finally, we run every proc / func / packaged units - no error must raise. +NOTES: + [13.06.2025] pzotov + Confirmed bug on 6.0.0.835-3da8317: + Error while parsing procedure "PUBLIC"."SP_TEST"'s BLR + -column "RDB$RELATION_NAME" does not exist in table/view "PUBLIC"."RDB$RELATIONS" + Checked on 6.0.0.835-0-b1fd7d8 +""" + +import pytest +import zipfile +import locale +from pathlib import Path +from firebird.qa import * +from firebird.driver import SrvRestoreFlag, DatabaseError +import time + +db = db_factory() + +act = python_act('db', substitutions=[('[ \t]+', ' ')]) + +tmp_fbk = temp_file('gh_8597-ods13_1.fbk') +tmp_fdb = temp_file('tmp_restore_8597.fdb') + +#------------------------------------------------------------------ +# Callback function: capture output of ERROR messages in restore (output must be empty): +def print_log(line: str) -> None: + if ( s:= line.strip()): + if 'ERROR' in s: + print(s) +#------------------------------------------------------------------ + +@pytest.mark.version('>=6.0') +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): + + zipped_fbk_file = zipfile.Path(act.files_dir / 'gh_8597-ods13_1.zip', at = 'gh_8597-ods13_1.fbk') + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) + # + restore_log = [] + test_sql = """ + set list on; + set blob all; + select p.o_id as proc_outcome from sp_test('rdb$database') p; + select fn_test('rdb$database') as func_outcome from rdb$database; + select p.o_id as pg_proc_outcome from pg_test.pg_sp_test('rdb$database') p; + select pg_test.pg_fn_test('rdb$database') as pg_func_outcome from rdb$database; + """ + with act.connect_server(encoding_errors = locale.getpreferredencoding()) as srv: + try: + srv.database.restore(backup=tmp_fbk, database=tmp_fdb, flags=SrvRestoreFlag.REPLACE, verbose=True, callback = print_log) + + act.isql( switches=[ str(tmp_fdb), '-q' ], connect_db = False, input = test_sql, combine_output = True ) + print(act.stdout) + except DatabaseError as e: + print(f'Restore failed:') + print(e.__str__()) + print(e.gds_codes) + except Exception as x: + print(x) + + act.expected_stdout = """ + PROC_OUTCOME 1 + FUNC_OUTCOME + PG_PROC_OUTCOME 2 + PG_FUNC_OUTCOME + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 91bb7bb4a4f3e01e56cf6e3f3d23c5cd1db870f9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Jun 2025 00:19:32 +0300 Subject: [PATCH 0553/1064] Added/Updated tests\bugs\gh_8601_test.py: Checked on 6.0.0.838-0-0b49fa8. --- tests/bugs/gh_8601_test.py | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/bugs/gh_8601_test.py diff --git a/tests/bugs/gh_8601_test.py b/tests/bugs/gh_8601_test.py new file mode 100644 index 00000000..83427c7c --- /dev/null +++ b/tests/bugs/gh_8601_test.py @@ -0,0 +1,44 @@ +#coding:utf-8 + +""" +ID: issue-8601 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8601 +TITLE: Charset and collation are not found in the search path when altering a table (FB 6.0 SQL schemas) +DESCRIPTION: +NOTES: + [14.06.2025] pzotov + Confirmed bug on 6.0.0.835, got: -Data type unknown / -CHARACTER SET "PUBLIC"."UTF8" is not defined + Checked on 6.0.0.838-0-0b49fa8. +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail on; + set list on; + recreate table t1 ( + id bigint not null primary key, + name varchar(10) character set utf8 + ); + + alter table t1 + alter name type varchar(10) character set utf8 collate unicode_ci_ai; + insert into t1(id, name) values(1, 'äÄöÖõÕšŠžŽ'); + insert into t1(id, name) values(2, 'AaOoOOSsZZ'); + select count(*) from t1 where name like 'AA%Zz'; +""" + +act = isql_act('db', test_script, substitutions=[ ('[ \\t]+', ' ') ]) + +expected_stdout = """ + COUNT 2 +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From cb51a9430ff9f5c3d8baef4b1c4630dbaa56f0df Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Jun 2025 11:00:32 +0300 Subject: [PATCH 0554/1064] Added/Updated tests\bugs\gh_8182_test.py: Checked on 6.0.0.838-0b49fa8; 5.0.3.1666-97178d0; 4.0.6.3213-f015c28 --- tests/bugs/gh_8182_test.py | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/bugs/gh_8182_test.py diff --git a/tests/bugs/gh_8182_test.py b/tests/bugs/gh_8182_test.py new file mode 100644 index 00000000..32a6ee26 --- /dev/null +++ b/tests/bugs/gh_8182_test.py @@ -0,0 +1,43 @@ +#coding:utf-8 + +""" +ID: issue-8182 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8182 +TITLE: IN predicate incorrectly handles single parenthesized subquery as IN-list, instead of table subquery +DESCRIPTION: +NOTES: + [15.06.2025] pzotov + Confirmed bug on 6.0.0.835-3da8317; 5.0.3.1661-cfcf0e8 + Checked on 6.0.0.838-0b49fa8; 5.0.3.1666-97178d0; 4.0.6.3213-f015c28 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set bail on; + set list on; + select sign(count(*)) + from rdb$character_sets + where rdb$character_set_id in ( + ( + select rdb$character_set_id + from rdb$collations + ) + ); + +""" + +act = isql_act('db', test_script, substitutions=[ ('[ \\t]+', ' ') ]) + +expected_stdout = """ + SIGN 1 +""" + +@pytest.mark.version('>=4.0.6') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 057362e5880b6d7b0c19383473cdd88452cc7ac8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 15 Jun 2025 11:01:55 +0300 Subject: [PATCH 0555/1064] Added/Updated tests\bugs\gh_8182_test.py: minor change: checked also on 3.0.13.33813-222a910, adjusted min_version --- tests/bugs/gh_8182_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_8182_test.py b/tests/bugs/gh_8182_test.py index 32a6ee26..e32b11fb 100644 --- a/tests/bugs/gh_8182_test.py +++ b/tests/bugs/gh_8182_test.py @@ -8,7 +8,7 @@ NOTES: [15.06.2025] pzotov Confirmed bug on 6.0.0.835-3da8317; 5.0.3.1661-cfcf0e8 - Checked on 6.0.0.838-0b49fa8; 5.0.3.1666-97178d0; 4.0.6.3213-f015c28 + Checked on 6.0.0.838-0b49fa8; 5.0.3.1666-97178d0; 4.0.6.3213-f015c28; 3.0.13.33813-222a910 """ import pytest @@ -36,7 +36,7 @@ SIGN 1 """ -@pytest.mark.version('>=4.0.6') +@pytest.mark.version('>=3.0.13') def test_1(act: Action): act.expected_stdout = expected_stdout act.execute(combine_output = True) From 9a54ccad6ea92509c22005d707e0b2bed66f56a3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 11:20:39 +0300 Subject: [PATCH 0556/1064] Added/Updated tests\functional\fkey\cascade\test_master_delete_if_no_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_delete_if_no_cascade.py | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py new file mode 100644 index 00000000..a8b15d29 --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py @@ -0,0 +1,73 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Attempt to delete record in master must fail if there is FK record in detail and FK was declared without CASCADE option +DESCRIPTION: + Test verifies RI mechanism when CASCADE option is used or missed: record in master may be deleted + only if there is no appropriate record in detail (with value in FK equal to PK value from master). + Work within a single transaction +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID = 1) + + REMAINED_ID 1 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + recreate table tmain(id int generated by default as identity primary key using index tmain_pk); + recreate table tdetl(id int generated by default as identity primary key, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); + insert into tmain(id) values(1); + insert into tmain(id) values(2); + insert into tdetl(id, pid) values(100, 1); + insert into tdetl(id, pid) values(101, null); + delete from tmain where id = 1; -- must FAIL + delete from tmain where id = 2; -- must PASS + select id as remained_id from tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From efc40e6bf4f470a6922005efb25a942ec6374e93 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 12:05:25 +0300 Subject: [PATCH 0557/1064] Added/Updated tests\functional\fkey\cascade\test_master_delete_if_no_cascade.py: Added code to check single- and multi-segmented PK/FK. --- .../test_master_delete_if_no_cascade.py | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py index a8b15d29..4bc5de10 100644 --- a/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py @@ -6,7 +6,8 @@ DESCRIPTION: Test verifies RI mechanism when CASCADE option is used or missed: record in master may be deleted only if there is no appropriate record in detail (with value in FK equal to PK value from master). - Work within a single transaction + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. NOTES: [17.06.2025] pzotov 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. @@ -47,7 +48,19 @@ -Foreign key references are present for the record -Problematic key value is (ID = 1) - REMAINED_ID 1 + REMAINED_MASTER_ID 1 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1, ID2 = 1, ID3 = 1) + REMAINED_MASTER_ID1 1 + REMAINED_MASTER_ID2 1 + REMAINED_MASTER_ID3 1 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 """ @pytest.mark.version('>=3.0') @@ -56,6 +69,8 @@ def test_1(act: Action): test_sql = """ set bail OFF; set list on; + + -- case-1: single segment PK: recreate table tmain(id int generated by default as identity primary key using index tmain_pk); recreate table tdetl(id int generated by default as identity primary key, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); insert into tmain(id) values(1); @@ -64,7 +79,26 @@ def test_1(act: Action): insert into tdetl(id, pid) values(101, null); delete from tmain where id = 1; -- must FAIL delete from tmain where id = 2; -- must PASS - select id as remained_id from tmain; + select id as remained_master_id from tmain; + select id as remained_detail_id from tdetl; + commit; + drop table tdetl; + drop table tmain; + -------------------------------------------- + -- case-2: multi-segment PK: + recreate table tmain(id1 int, id2 int, id3 int, primary key(id1, id2, id3) using index tmain_pk); + recreate table tdetl(id int primary key, pid1 int, pid2 int, pid3 int, constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain); + insert into tmain(id1, id2, id3) values(1,1,1); + insert into tmain(id1, id2, id3) values(1,1,2); + insert into tdetl(id, pid1, pid2, pid3) values(100, 1, 1, 1); + insert into tdetl(id, pid1, pid2, pid3) values(101, 1, 1, null); + delete from tmain where id1 = 1 and id2 = 1 and id3 = 1; -- must FAIL + delete from tmain where id1 = 1 and id2 = 1 and id3 = 2; -- must PASS + select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain; + select id as remained_detail_id from tdetl; + commit; + drop table tdetl; + drop table tmain; """ act.expected_stdout = expected_stdout From ac066080796b39bb0acfe7facab7c2faaf206179 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 12:21:31 +0300 Subject: [PATCH 0558/1064] Renamed to better suit its purposes --- ...te_if_no_cascade.py => test_master_pk_delete_if_no_cascade.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/functional/fkey/cascade/{test_master_delete_if_no_cascade.py => test_master_pk_delete_if_no_cascade.py} (100%) diff --git a/tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py similarity index 100% rename from tests/functional/fkey/cascade/test_master_delete_if_no_cascade.py rename to tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py From db6eb21fb45dd554e0db8081c039ed5fbb449d1a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 13:20:24 +0300 Subject: [PATCH 0559/1064] Added/Updated tests\functional\fkey\cascade\test_master_uk_delete_if_no_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_uk_delete_if_no_cascade.py | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py new file mode 100644 index 00000000..e5a97989 --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py @@ -0,0 +1,160 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Attempt to delete record in master with UK must fail if there is FK record in detail and FK was declared without CASCADE option +DESCRIPTION: + Test verifies RI mechanism when CASCADE option is used or missed: record in master with UNIQUE constraint may be deleted + only if there is no appropriate record in detail (with value in FK equal to UK value from master) or all key fields are NULL. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID = 1000) + REMAINED_MASTER_ID 1000 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 + + MON$VARIABLE_NAME FK_VIOLATION_335544466 + MON$VARIABLE_VALUE 7 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment UK: + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl(id int primary key, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); + insert into tmain(id) values(null); + insert into tmain(id) values(1000); + insert into tmain(id) values(2000); + insert into tdetl(id, pid) values(100, 1000); + insert into tdetl(id, pid) values(101, null); + delete from tmain where id = 1000; -- must FAIL + delete from tmain where id = 2000; -- must PASS + delete from tmain where id is null; -- must PASS + select id as remained_master_id from tmain; + select id as remained_detail_id from tdetl; + commit; + drop table tdetl; + drop table tmain; + + --###################################################### + + -- case-2: multi-segment UK: + recreate table tmain(id1 int, id2 int, id3 int, unique(id1, id2, id3) using index tmain_uk); + recreate table tdetl(id int primary key, pid1 int, pid2 int, pid3 int, constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain(id1, id2, id3)); + + insert into tmain(id1, id2, id3) + with + a as ( + select 1000 as v from rdb$database union all + select 1000 as v from rdb$database union all + select null as v from rdb$database + ) + select distinct a1.v, a2.v, a3.v + from a a1 + cross join a a2 + cross join a a3 + ; + insert into tdetl(id, pid1, pid2, pid3) + select row_number()over(), id1, id2, id3 + from tmain + order by id1, id2, id3; + + -- tmain: + -- ID1 ID2 ID3 + -- ============ ============ ============ + -- + -- 1000 + -- 1000 + -- 1000 1000 + -- 1000 + -- 1000 1000 + -- 1000 1000 + -- 1000 1000 1000 + + -- tdetl: + -- ID PID1 PID2 PID3 + -- ============ ============ ============ ============ + -- 1 + -- 2 1000 + -- 3 1000 + -- 4 1000 1000 + -- 5 1000 + -- 6 1000 1000 + -- 7 1000 1000 + -- 8 1000 1000 1000 + + + delete from tmain where coalesce(id1, id2, id3) is null; -- must PASS because all key fields are null + + -- Any records in tmain with at least one NOT null value among ID1 ... ID3 must not be deleted in following code. + -- We try to delete every row with accumulating count of errors (for appropriate gdscode which must be the same: 335544466). + -- Finally, we check content of mon$context_variables table: number of accumulated errors must be 7. + set term ^; + execute block as + declare v_ctx_name varchar(255); + begin + for select id1, id2, id3 from tmain where coalesce(id1, id2, id3) is NOT null as cursor c + do begin + -- 335544466 : violation of FOREIGN KEY constraint "TDETL_FK" on table "PUBLIC"."TDETL" + delete from tmain where current of c; + when any do + begin + v_ctx_name = 'FK_VIOLATION_' || gdscode; + rdb$set_context('USER_SESSION', v_ctx_name, coalesce(cast( rdb$get_context('USER_SESSION', v_ctx_name) as int), 0) + 1); + end + end + end ^ + set term ;^ + select mon$variable_name, mon$variable_value from mon$context_variables where mon$variable_name starting with 'FK_VIOLATION_'; + commit; + drop table tdetl; + drop table tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From 60a57bfd260913a9bb01704bb6a07dc20df0780b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:35:40 +0300 Subject: [PATCH 0560/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_update_if_no_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_pk_update_if_no_cascade.py | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py new file mode 100644 index 00000000..4eee37b1 --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py @@ -0,0 +1,112 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Attempt to delete record in master must fail if there is FK record in detail and FK was declared without CASCADE option +DESCRIPTION: + Test verifies RI mechanism when CASCADE option is used or missed: PK-column(s) in master may be updated + only if there is no appropriate record in detail, i.e. with value in FK column(s) equal to PK value(s) from master. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID = 1) + REMAINED_MASTER_ID 1 + REMAINED_MASTER_ID -2 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1, ID2 = 1, ID3 = 1) + REMAINED_MASTER_ID1 1 + REMAINED_MASTER_ID2 1 + REMAINED_MASTER_ID3 1 + REMAINED_MASTER_ID1 -2 + REMAINED_MASTER_ID2 -2 + REMAINED_MASTER_ID3 -2 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment PK: + recreate table tmain(id int generated by default as identity primary key using index tmain_pk); + recreate table tdetl(id int generated by default as identity primary key, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); + insert into tmain(id) values(1); + insert into tmain(id) values(2); + insert into tdetl(id, pid) values(100, 1); + insert into tdetl(id, pid) values(101, null); + update tmain set id = -id where id = 1; -- must FAIL + update tmain set id = -id where id = 2; -- must PASS + select id as remained_master_id from tmain; + select id as remained_detail_id from tdetl; + commit; + drop table tdetl; + drop table tmain; + -------------------------------------------- + + + -- case-2: multi-segment PK: + recreate table tmain(id1 int, id2 int, id3 int, primary key(id1, id2, id3) using index tmain_pk); + recreate table tdetl(id int primary key, pid1 int, pid2 int, pid3 int, constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain); + insert into tmain(id1, id2, id3) values(1,1,1); + insert into tmain(id1, id2, id3) values(1,1,2); + insert into tdetl(id, pid1, pid2, pid3) values(100, 1, 1, 1); + insert into tdetl(id, pid1, pid2, pid3) values(101, 1, 1, null); + update tmain set id1 = -1, id2 = -1, id3 = -1 where id1 = 1 and id2 = 1 and id3 = 1; -- must FAIL + update tmain set id1 = -2, id2 = -2, id3 = -2 where id1 = 1 and id2 = 1 and id3 = 2; -- must PASS + select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain; + select id as remained_detail_id from tdetl; + commit; + drop table tdetl; + drop table tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From 9c8af5aaf2b8938c894b84bda539e9c471f9a7f8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:37:00 +0300 Subject: [PATCH 0561/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_update_if_no_cascade.py: minor change: adjusted TITLE text. --- .../fkey/cascade/test_master_pk_update_if_no_cascade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py index 4eee37b1..798cc506 100644 --- a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py @@ -2,7 +2,7 @@ """ ID: n/a -TITLE: Attempt to delete record in master must fail if there is FK record in detail and FK was declared without CASCADE option +TITLE: Attempt to update PK column(s) in master must fail if there is FK record in detail and FK was declared without CASCADE option DESCRIPTION: Test verifies RI mechanism when CASCADE option is used or missed: PK-column(s) in master may be updated only if there is no appropriate record in detail, i.e. with value in FK column(s) equal to PK value(s) from master. From e5cbb559068e4a609b50e0108ddf9be0dea5bc6a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:44:28 +0300 Subject: [PATCH 0562/1064] Added 'order by' to avoid inpredictable output. Adjusted expected out. --- .../test_master_pk_delete_if_no_cascade.py | 8 ++++---- .../test_master_pk_update_if_no_cascade.py | 16 ++++++++-------- .../test_master_uk_delete_if_no_cascade.py | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py index 4bc5de10..bec37de9 100644 --- a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py @@ -79,8 +79,8 @@ def test_1(act: Action): insert into tdetl(id, pid) values(101, null); delete from tmain where id = 1; -- must FAIL delete from tmain where id = 2; -- must PASS - select id as remained_master_id from tmain; - select id as remained_detail_id from tdetl; + select id as remained_master_id from tmain order by id; + select id as remained_detail_id from tdetl order by id; commit; drop table tdetl; drop table tmain; @@ -94,8 +94,8 @@ def test_1(act: Action): insert into tdetl(id, pid1, pid2, pid3) values(101, 1, 1, null); delete from tmain where id1 = 1 and id2 = 1 and id3 = 1; -- must FAIL delete from tmain where id1 = 1 and id2 = 1 and id3 = 2; -- must PASS - select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain; - select id as remained_detail_id from tdetl; + select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain order by id1, id2, id3; + select id as remained_detail_id from tdetl order by id; commit; drop table tdetl; drop table tmain; diff --git a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py index 798cc506..dc2eeb1f 100644 --- a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py @@ -47,8 +47,8 @@ violation of FOREIGN KEY constraint TDETL_FK on table TDETL -Foreign key references are present for the record -Problematic key value is (ID = 1) - REMAINED_MASTER_ID 1 REMAINED_MASTER_ID -2 + REMAINED_MASTER_ID 1 REMAINED_DETAIL_ID 100 REMAINED_DETAIL_ID 101 @@ -56,12 +56,12 @@ violation of FOREIGN KEY constraint TDETL_FK on table TDETL -Foreign key references are present for the record -Problematic key value is (ID1 = 1, ID2 = 1, ID3 = 1) - REMAINED_MASTER_ID1 1 - REMAINED_MASTER_ID2 1 - REMAINED_MASTER_ID3 1 REMAINED_MASTER_ID1 -2 REMAINED_MASTER_ID2 -2 REMAINED_MASTER_ID3 -2 + REMAINED_MASTER_ID1 1 + REMAINED_MASTER_ID2 1 + REMAINED_MASTER_ID3 1 REMAINED_DETAIL_ID 100 REMAINED_DETAIL_ID 101 """ @@ -82,8 +82,8 @@ def test_1(act: Action): insert into tdetl(id, pid) values(101, null); update tmain set id = -id where id = 1; -- must FAIL update tmain set id = -id where id = 2; -- must PASS - select id as remained_master_id from tmain; - select id as remained_detail_id from tdetl; + select id as remained_master_id from tmain order by id; + select id as remained_detail_id from tdetl order by id; commit; drop table tdetl; drop table tmain; @@ -99,8 +99,8 @@ def test_1(act: Action): insert into tdetl(id, pid1, pid2, pid3) values(101, 1, 1, null); update tmain set id1 = -1, id2 = -1, id3 = -1 where id1 = 1 and id2 = 1 and id3 = 1; -- must FAIL update tmain set id1 = -2, id2 = -2, id3 = -2 where id1 = 1 and id2 = 1 and id3 = 2; -- must PASS - select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain; - select id as remained_detail_id from tdetl; + select id1 as remained_master_id1, id2 as remained_master_id2, id3 as remained_master_id3 from tmain order by id1, id2, id3; + select id as remained_detail_id from tdetl order by id; commit; drop table tdetl; drop table tmain; diff --git a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py index e5a97989..385337c3 100644 --- a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py @@ -73,8 +73,8 @@ def test_1(act: Action): delete from tmain where id = 1000; -- must FAIL delete from tmain where id = 2000; -- must PASS delete from tmain where id is null; -- must PASS - select id as remained_master_id from tmain; - select id as remained_detail_id from tdetl; + select id as remained_master_id from tmain order by id; + select id as remained_detail_id from tdetl order by id; commit; drop table tdetl; drop table tmain; From 02de2dbb566dc015e933ea941e5fa2bfd64a3495 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:55:02 +0300 Subject: [PATCH 0563/1064] Added/Updated tests\functional\fkey\cascade\test_master_uk_update_if_no_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_uk_update_if_no_cascade.py | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py new file mode 100644 index 00000000..a2619d56 --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py @@ -0,0 +1,163 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Attempt to update UK column(s) in master must fail if there is FK record in detail and FK was declared without CASCADE option +DESCRIPTION: + Test verifies RI mechanism when CASCADE option is used or missed: key columns in master with UNIQUE constraint may be updated + only if there is no appropriate record in detail (with value in FK equal to UK value from master) or all key fields are NULL. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID = 1000) + REMAINED_MASTER_ID -2000 + REMAINED_MASTER_ID 1000 + REMAINED_MASTER_ID 3000 + REMAINED_DETAIL_ID 100 + REMAINED_DETAIL_ID 101 + + MON$VARIABLE_NAME FK_VIOLATION_335544466 + MON$VARIABLE_VALUE 7 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment UK: + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl(id int primary key, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); + insert into tmain(id) values(null); + insert into tmain(id) values(1000); + insert into tmain(id) values(2000); + insert into tdetl(id, pid) values(100, 1000); + insert into tdetl(id, pid) values(101, null); + update tmain set id = -id where id = 1000; -- must FAIL + update tmain set id = -id where id = 2000; -- must PASS + update tmain set id = 3000 where id is null; -- must PASS + select id as remained_master_id from tmain order by id; + select id as remained_detail_id from tdetl order by id; + commit; + drop table tdetl; + drop table tmain; + + --###################################################### + + -- case-2: multi-segment UK: + recreate table tmain(id1 int, id2 int, id3 int, unique(id1, id2, id3) using index tmain_uk); + recreate table tdetl(id int primary key, pid1 int, pid2 int, pid3 int, constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain(id1, id2, id3)); + + insert into tmain(id1, id2, id3) + with + a as ( + select 1000 as v from rdb$database union all + select 1000 as v from rdb$database union all + select null as v from rdb$database + ) + select distinct a1.v, a2.v, a3.v + from a a1 + cross join a a2 + cross join a a3 + ; + insert into tdetl(id, pid1, pid2, pid3) + select row_number()over(), id1, id2, id3 + from tmain + order by id1, id2, id3; + + -- tmain: + -- ID1 ID2 ID3 + -- ============ ============ ============ + -- + -- 1000 + -- 1000 + -- 1000 1000 + -- 1000 + -- 1000 1000 + -- 1000 1000 + -- 1000 1000 1000 + + -- tdetl: + -- ID PID1 PID2 PID3 + -- ============ ============ ============ ============ + -- 1 + -- 2 1000 + -- 3 1000 + -- 4 1000 1000 + -- 5 1000 + -- 6 1000 1000 + -- 7 1000 1000 + -- 8 1000 1000 1000 + + + -- must PASS because no detail can refer to the record in master which contain nulls in all key columns: + update tmain set id1 = 9999, id2 = 9999, id3 = 9999 where coalesce(id1, id2, id3) is null; + + -- Any records in tmain with at least one NOT null value among ID1 ... ID3 must not be updated in following code. + -- We try to update every row with accumulating count of errors (for appropriate gdscode which must be the same: 335544466). + -- Finally, we check content of mon$context_variables table: number of accumulated errors must be 7. + set term ^; + execute block as + declare v_ctx_name varchar(255); + begin + for select id1, id2, id3 from tmain where coalesce(id1, id2, id3) is NOT null as cursor c + do begin + -- 335544466 : violation of FOREIGN KEY constraint "TDETL_FK" on table "PUBLIC"."TDETL" + update tmain set id1 = null, id2 = null, id3 = null where current of c; + when any do + begin + v_ctx_name = 'FK_VIOLATION_' || gdscode; + rdb$set_context('USER_SESSION', v_ctx_name, coalesce(cast( rdb$get_context('USER_SESSION', v_ctx_name) as int), 0) + 1); + end + end + end ^ + set term ;^ + select mon$variable_name, mon$variable_value from mon$context_variables where mon$variable_name starting with 'FK_VIOLATION_'; + commit; + drop table tdetl; + drop table tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From b81497ae06d0b232ec7a6c11c827db519b4466aa Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:55:40 +0300 Subject: [PATCH 0564/1064] Added __init__.py --- tests/functional/fkey/cascade/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/functional/fkey/cascade/__init__.py diff --git a/tests/functional/fkey/cascade/__init__.py b/tests/functional/fkey/cascade/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/fkey/cascade/__init__.py @@ -0,0 +1 @@ +# Python module From b7891429931feef2a54cd61ed7041b59e75e7668 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 14:56:00 +0300 Subject: [PATCH 0565/1064] Added __init__.py --- tests/functional/sqlancer/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/functional/sqlancer/__init__.py diff --git a/tests/functional/sqlancer/__init__.py b/tests/functional/sqlancer/__init__.py new file mode 100644 index 00000000..4adc9840 --- /dev/null +++ b/tests/functional/sqlancer/__init__.py @@ -0,0 +1 @@ +# Python module From 325cb9e6d275d55950106926d2f8f3b51ec20413 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 15:16:03 +0300 Subject: [PATCH 0566/1064] Added/Updated tests\functional\fkey\cascade\test_prohibit_change_of_key_column_types.py: Checked on 6.0.0.838; 3.0.13.33813. --- ...est_prohibit_change_of_key_column_types.py | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py diff --git a/tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py b/tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py new file mode 100644 index 00000000..3953fec0 --- /dev/null +++ b/tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py @@ -0,0 +1,194 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Attempt to change type of any column involved in PK/FK constraints must fail. +DESCRIPTION: + Single- and multi-segmented PK/UK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set autoddl off; + set list on; + + -- all following statements shoudl FAIL: + + -- case-1a: single segment PK + -- ------------------------- + recreate table tmain_single_pk(id_pk int primary key using index tmain_pk); + recreate table tdetl_single_pk(id_pk int primary key, pid2pk int, constraint tdetl_fk foreign key(pid2pk) references tmain_single_pk(id_pk)); + commit; + alter table tmain_single_pk alter column id_pk type bigint; + alter table tdetl_single_pk alter column pid2pk type bigint; + commit; + drop table tdetl_single_pk; + drop table tmain_single_pk; + + -- case-1b: single segment UK + -- ------------------------- + recreate table tmain_single_uk(id_uk int unique using index tmain_pk); + recreate table tdetl_single_uk(id int primary key, pid2uk int, constraint tdetl_fk foreign key(pid2uk) references tmain_single_uk(id_uk)); + commit; + alter table tmain_single_uk alter column id_uk type bigint; + alter table tdetl_single_uk alter column pid2uk type bigint; + commit; + drop table tdetl_single_uk; + drop table tmain_single_uk; + + -- case-2a: multi segment PK + -- ------------------------- + recreate table tmain_multi_pk(pk_id1 int, pk_id2 int, primary key(pk_id1, pk_id2) using index tmain_pk); + recreate table tdetl_multi_pk(id_pk int primary key, fk_id1 int, fk_id2 int, constraint tdetl_fk foreign key(fk_id1, fk_id2) references tmain_multi_pk(pk_id1, pk_id2)); + commit; + alter table tmain_multi_pk alter column pk_id2 type bigint; + alter table tdetl_multi_pk alter column fk_id2 type bigint; + commit; + drop table tdetl_multi_pk; + drop table tmain_multi_pk; + + -- case-2b: multi segment UK + -- ------------------------- + recreate table tmain_multi_uk(pk_id1 int, pk_id2 int, unique(pk_id1, pk_id2) using index tmain_uk); + recreate table tdetl_multi_uk(id_pk int primary key, fk_id1 int, fk_id2 int, constraint tdetl_fk foreign key(fk_id1, fk_id2) references tmain_multi_uk(pk_id1, pk_id2)); + commit; + alter table tmain_multi_uk alter column pk_id2 type bigint; + alter table tdetl_multi_uk alter column fk_id2 type bigint; + commit; + drop table tdetl_multi_uk; + drop table tmain_multi_uk; + """ + + expected_stdout_3x = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TMAIN_SINGLE_PK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TDETL_SINGLE_PK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TMAIN_SINGLE_UK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TDETL_SINGLE_UK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TMAIN_MULTI_PK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TDETL_MULTI_PK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TMAIN_MULTI_UK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TDETL_MULTI_UK failed + -action cancelled by trigger (1) to preserve data integrity + -Cannot update index segment used by an Integrity Constraint + """ + + + expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TMAIN_SINGLE_PK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TDETL_SINGLE_PK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TMAIN_SINGLE_UK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TDETL_SINGLE_UK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TMAIN_MULTI_PK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TDETL_MULTI_PK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TMAIN_MULTI_UK failed + -Cannot update index segment used by an Integrity Constraint + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TDETL_MULTI_UK failed + -Cannot update index segment used by an Integrity Constraint + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From e8dcbb8229652e6ab45468c258dfd2fe46f85c12 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 17:27:07 +0300 Subject: [PATCH 0567/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_diff_table_types.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_restrictions_for_diff_table_types.py | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/functional/fkey/common/test_restrictions_for_diff_table_types.py diff --git a/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py b/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py new file mode 100644 index 00000000..315a2dd1 --- /dev/null +++ b/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py @@ -0,0 +1,137 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Tables involved in referential integrity have to meet restrictions when their types differ (persistent vs GTT; connection-bound vs transaction-bound). +DESCRIPTION: + Test verifies that: + * GTTs and regular ("permanent") tables cannot reference one another. + * A connection-bound ("PRESERVE ROWS") GTT cannot reference a transaction-bound ("DELETE ROWS") GTT + Work within a single attachment. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + 3. See doc: + https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html#fblangref50-ddl-tbl-gtt-restrictions + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At line \\d+.*', '')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + set count on; + + recreate table tmain_fixed (id int primary key using index tmain_fixed_pk); + + -- case-1a: GTT of type 'on commit PRESERVE rows' can not refer to persistent table: + recreate global temporary table tdetl_gtt_keep_rows(id int primary key using index tdetl_pk, pid int references tmain_fixed(id) using index tdetl_keep_fk) on commit preserve rows; + select * from rdb$relations where rdb$relation_name = upper('tdetl_gtt_keep_rows'); + + -- case-1b: GTT of type 'on commit DELETE rows' can not refer to persistent table: + recreate global temporary table tdetl_gtt_kill_rows(id int primary key using index tdetl_pk, pid int references tmain_fixed(id) using index tdetl_kill_fk) on commit delete rows; + select * from rdb$relations where rdb$relation_name = upper('tdetl_gtt_kill_rows'); + commit; + drop table tmain_fixed; + + + -- case-1c: persistent table can not refer to GTT of type 'on commit PRESERVE rows': + recreate global temporary table tmain_gtt_keep_rows(id int primary key using index tmain_keep_pk) on commit preserve rows; + recreate table tdetl_fixed(id int primary key using index tdetl_fixed_pk, pid int references tmain_gtt_keep_rows(id) using index tdetl_fixed_fk); + select * from rdb$relations where rdb$relation_name = upper('tdetl_fixed'); + commit; + drop table tmain_gtt_keep_rows; + + -- case-1d: persistent table can not refer to GTT of type 'on commit DELETE rows': + recreate global temporary table tmain_gtt_kill_rows(id int primary key using index tmain_kill_pk) on commit delete rows; + recreate table tdetl_fixed(id int primary key using index tdetl_fixed_pk, pid int references tmain_gtt_kill_rows(id) using index tdetl_fixed_fk); + select * from rdb$relations where rdb$relation_name = upper('tdetl_fixed'); + commit; + drop table tmain_gtt_kill_rows; + + + -- case-2a: GTT of type 'on commit PRESERVE rows' cannot refer a GTT of type 'on commit DELETE rows' + recreate global temporary table tmain_gtt_kill_rows(id int primary key using index tmain_kill_pk) on commit delete rows; + recreate global temporary table tdetl_gtt_keep_rows(id int primary key using index tdetl_keep_pk, pid int references tmain_gtt_kill_rows(id) using index tdetl_keep_fk) on commit preserve rows; + select * from rdb$relations where rdb$relation_name = upper('tdetl_gtt_keep_rows'); + commit; + drop table tmain_gtt_kill_rows; + + + -- case-2b: GTT of type 'on commit DELETE rows' *** CAN ** refer a GTT of type 'on commit PRESERVE rows' + recreate global temporary table tmain_gtt_keep_rows(id int primary key using index tmain_keep_pk) on commit preserve rows; + recreate global temporary table tdetl_gtt_kill_rows(id int primary key using index tdetl_kill_pk, pid int references tmain_gtt_keep_rows(id) using index tdetl_kill_fk) on commit delete rows; + commit; + set count off; + select count(*) from rdb$relations where rdb$relation_name = upper('tdetl_gtt_kill_rows'); + commit; + """ + + expected_stdout = """ + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -RECREATE TABLE TDETL_GTT_KEEP_ROWS failed + -global temporary table TDETL_GTT_KEEP_ROWS of type ON COMMIT PRESERVE ROWS cannot reference persistent table TMAIN_FIXED + Records affected: 0 + + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -RECREATE TABLE TDETL_GTT_KILL_ROWS failed + -global temporary table TDETL_GTT_KILL_ROWS of type ON COMMIT DELETE ROWS cannot reference persistent table TMAIN_FIXED + Records affected: 0 + + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -RECREATE TABLE TDETL_FIXED failed + -persistent table TDETL_FIXED cannot reference global temporary table TMAIN_GTT_KEEP_ROWS of type ON COMMIT PRESERVE ROWS + Records affected: 0 + + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -RECREATE TABLE TDETL_FIXED failed + -persistent table TDETL_FIXED cannot reference global temporary table TMAIN_GTT_KILL_ROWS of type ON COMMIT DELETE ROWS + Records affected: 0 + + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -RECREATE TABLE TDETL_GTT_KEEP_ROWS failed + -global temporary table TDETL_GTT_KEEP_ROWS of type ON COMMIT PRESERVE ROWS cannot reference global temporary table TMAIN_GTT_KILL_ROWS of type ON COMMIT DELETE ROWS + Records affected: 0 + + COUNT 1 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From 5df5394dc248dae77515e74cc1ad062dcaaa326c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 17:28:13 +0300 Subject: [PATCH 0568/1064] Moved test in proper folder to better suit its function --- .../test_prohibit_change_of_key_column_types.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/functional/fkey/{cascade => common}/test_prohibit_change_of_key_column_types.py (100%) diff --git a/tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py b/tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py similarity index 100% rename from tests/functional/fkey/cascade/test_prohibit_change_of_key_column_types.py rename to tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py From b1fe5cf176d311fc1d769b77235b8f9dc465e56c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 17:39:57 +0300 Subject: [PATCH 0569/1064] minor change: adjust description --- .../fkey/cascade/test_master_pk_delete_if_no_cascade.py | 2 +- .../fkey/cascade/test_master_pk_update_if_no_cascade.py | 2 +- .../fkey/cascade/test_master_uk_delete_if_no_cascade.py | 2 +- .../fkey/cascade/test_master_uk_update_if_no_cascade.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py index bec37de9..bce833a0 100644 --- a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py @@ -4,7 +4,7 @@ ID: n/a TITLE: Attempt to delete record in master must fail if there is FK record in detail and FK was declared without CASCADE option DESCRIPTION: - Test verifies RI mechanism when CASCADE option is used or missed: record in master may be deleted + Test verifies RI mechanism when CASCADE option missed: record in master may be deleted only if there is no appropriate record in detail (with value in FK equal to PK value from master). Single- and multi-segmented PK/FK are checked. Work within a single transaction. diff --git a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py index dc2eeb1f..13bc6506 100644 --- a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py @@ -4,7 +4,7 @@ ID: n/a TITLE: Attempt to update PK column(s) in master must fail if there is FK record in detail and FK was declared without CASCADE option DESCRIPTION: - Test verifies RI mechanism when CASCADE option is used or missed: PK-column(s) in master may be updated + Test verifies RI mechanism when CASCADE option missed: PK-column(s) in master may be updated only if there is no appropriate record in detail, i.e. with value in FK column(s) equal to PK value(s) from master. Single- and multi-segmented PK/FK are checked. Work within a single transaction. diff --git a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py index 385337c3..978f6412 100644 --- a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py @@ -4,7 +4,7 @@ ID: n/a TITLE: Attempt to delete record in master with UK must fail if there is FK record in detail and FK was declared without CASCADE option DESCRIPTION: - Test verifies RI mechanism when CASCADE option is used or missed: record in master with UNIQUE constraint may be deleted + Test verifies RI mechanism when CASCADE option missed: record in master with UNIQUE constraint may be deleted only if there is no appropriate record in detail (with value in FK equal to UK value from master) or all key fields are NULL. Single- and multi-segmented PK/FK are checked. Work within a single transaction. diff --git a/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py index a2619d56..fd3eedfe 100644 --- a/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py @@ -4,7 +4,7 @@ ID: n/a TITLE: Attempt to update UK column(s) in master must fail if there is FK record in detail and FK was declared without CASCADE option DESCRIPTION: - Test verifies RI mechanism when CASCADE option is used or missed: key columns in master with UNIQUE constraint may be updated + Test verifies RI mechanism when CASCADE option missed: key columns in master with UNIQUE constraint may be updated only if there is no appropriate record in detail (with value in FK equal to UK value from master) or all key fields are NULL. Single- and multi-segmented PK/FK are checked. Work within a single transaction. From faf8ba8b1040db8cfcadb9b126f1632f455f1e29 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 17:56:10 +0300 Subject: [PATCH 0570/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_on_update_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_pk_on_update_cascade.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py b/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py new file mode 100644 index 00000000..4d7342ce --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py @@ -0,0 +1,111 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Updating PK column(s) in master must cause changes in appropriate detail column(s) if 'ON UPDATE CASCADE' option is used +DESCRIPTION: + Test verifies RI mechanism when ON UPDATE CASCADE option is used: updating record in master should cause appropriate updates in detail. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + DETAIL_ID 100 + DETAIL_PID -1 + + DETAIL_ID 101 + DETAIL_PID -1 + + DETAIL_ID 200 + DETAIL_PID1 -1 + DETAIL_PID2 -1 + DETAIL_PID3 -3 + + DETAIL_ID 201 + DETAIL_PID1 -1 + DETAIL_PID2 -1 + DETAIL_PID3 -3 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment PK: + recreate table tmain(id int generated by default as identity primary key using index tmain_pk); + recreate table tdetl( + id int generated by default as identity primary key + ,pid int + ,constraint tdetl_fk foreign key(pid) references tmain + ON UPDATE CASCADE + ); + insert into tmain(id) values(1); + insert into tdetl(id, pid) values(100, 1); + insert into tdetl(id, pid) values(101, 1); + update tmain set id = -id where id = 1; -- must PASS and cause update in tdetl + select id as detail_id, pid as detail_pid from tdetl order by id; + commit; + drop table tdetl; + drop table tmain; + + -------------------------------------------- + + -- case-2: multi-segment PK: + recreate table tmain(id1 int, id2 int, id3 int, primary key(id1, id2, id3) using index tmain_pk); + recreate table tdetl( + id int primary key + ,pid1 int + ,pid2 int + ,pid3 int + ,constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain + ON UPDATE CASCADE + ); + insert into tmain(id1, id2, id3) values(1,1,1); + insert into tdetl(id, pid1, pid2, pid3) values(200, 1, 1, 1); + insert into tdetl(id, pid1, pid2, pid3) values(201, 1, 1, 1); + update tmain set id1 = -id1, id2 = -id2, id3 = -3 where id1 = 1 and id2 = 1 and id3 = 1; -- must PASS and cause update in tdetl + select id as detail_id, pid1 as detail_pid1, pid2 as detail_pid2, pid3 as detail_pid3 from tdetl order by id; + commit; + drop table tdetl; + drop table tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From 689a4ab378d78532926d74aa76ff53eede714d40 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 17 Jun 2025 22:50:03 +0300 Subject: [PATCH 0571/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_on_delete_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_pk_on_delete_cascade.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py new file mode 100644 index 00000000..e7afe3a7 --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py @@ -0,0 +1,98 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Deleting record in master must cause deletions in appropriate detail if 'ON DELETE CASCADE' option is used +DESCRIPTION: + Test verifies RI mechanism when ON DELETE CASCADE option is used. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + REMAINED_IN_TDETL_CASE_1 0 + REMAINED_IN_TDETL_CASE_2 0 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment PK: + recreate table tmain(id int generated by default as identity primary key using index tmain_pk); + recreate table tdetl( + id int generated by default as identity primary key + ,pid int + ,constraint tdetl_fk foreign key(pid) references tmain + ON DELETE CASCADE + ); + insert into tmain(id) values(1); + insert into tdetl(id, pid) values(100, 1); + insert into tdetl(id, pid) values(101, 1); + delete from tmain where id = 1; -- must PASS and cause deletion of all records in tdetl + select count(*) as remained_in_tdetl_case_1 from tdetl; + commit; + drop table tdetl; + drop table tmain; + + -------------------------------------------- + + -- case-2: multi-segment PK: + recreate table tmain(id1 int, id2 int, id3 int, primary key(id1, id2, id3) using index tmain_pk); + recreate table tdetl( + id int primary key + ,pid1 int + ,pid2 int + ,pid3 int + ,constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain + ON DELETE CASCADE + ); + insert into tmain(id1, id2, id3) values(1,1,1); + insert into tdetl(id, pid1, pid2, pid3) values(200, 1, 1, 1); + insert into tdetl(id, pid1, pid2, pid3) values(201, 1, 1, 1); + delete from tmain where id1 = 1 and id2 = 1 and id3 = 1; -- must PASS and cause deletion of all records in tdetl + select count(*) as remained_in_tdetl_case_2 from tdetl; + commit; + drop table tdetl; + drop table tmain; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From bd9beeb61a6888348d820a716030e9f72b9e6d38 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 18 Jun 2025 15:03:21 +0300 Subject: [PATCH 0572/1064] Added/Updated tests\functional\fkey\cascade\test_master_uk_on_update_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_master_uk_on_update_cascade.py | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_master_uk_on_update_cascade.py diff --git a/tests/functional/fkey/cascade/test_master_uk_on_update_cascade.py b/tests/functional/fkey/cascade/test_master_uk_on_update_cascade.py new file mode 100644 index 00000000..985b269b --- /dev/null +++ b/tests/functional/fkey/cascade/test_master_uk_on_update_cascade.py @@ -0,0 +1,122 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Updating PK column(s) in master must cause changes in appropriate detail column(s) if 'ON UPDATE CASCADE' option is used +DESCRIPTION: + Test verifies RI mechanism when ON UPDATE CASCADE option is used: updating record in master should cause appropriate updates in detail. + Single- and multi-segmented PK/FK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_UK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID = -1) + + DETAIL_ID 100 + DETAIL_PID -1 + DETAIL_ID 101 + DETAIL_PID -1 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key references are present for the record + -Problematic key value is (ID1 = -1, ID2 = -1, ID3 = -1) + + DETAIL_ID 200 + DETAIL_PID1 -1 + DETAIL_PID2 -1 + DETAIL_PID3 -1 + DETAIL_ID 201 + DETAIL_PID1 -1 + DETAIL_PID2 -1 + DETAIL_PID3 -1 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment UK: + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl( + id int primary key + ,pid int + ,constraint tdetl_uk foreign key(pid) references tmain(id) + ON UPDATE CASCADE + ); + insert into tmain(id) values(1); + insert into tdetl(id, pid) values(100, 1); + insert into tdetl(id, pid) values(101, 1); + update tmain set id = -1 where id = 1; -- must PASS and cause update in tdetl + update tmain set id = null where id = -1; -- must FAIL: 'on update SET NULL' must be for this case! + select id as detail_id, pid as detail_pid from tdetl order by id; + commit; + drop table tdetl; + drop table tmain; + + -------------------------------------------- + + -- case-2: multi-segment UK: + recreate table tmain(id1 int, id2 int, id3 int, unique(id1, id2, id3) using index tmain_uk); + recreate table tdetl( + id int primary key + ,pid1 int + ,pid2 int + ,pid3 int + ,constraint tdetl_fk foreign key(pid1, pid2, pid3) references tmain(id1, id2, id3) + ON UPDATE CASCADE + ); + insert into tmain(id1, id2, id3) values(1,1,1); + insert into tdetl(id, pid1, pid2, pid3) values(200, 1, 1, 1); + insert into tdetl(id, pid1, pid2, pid3) values(201, 1, 1, 1); + update tmain set id1 = -id1, id2 = -id2, id3 = -1 where id1 = 1 and id2 = 1 and id3 = 1; -- must PASS and cause update in tdetl + update tmain set id3 = null where id3 = -1; + select id as detail_id, pid1 as detail_pid1, pid2 as detail_pid2, pid3 as detail_pid3 from tdetl order by id; + commit; + drop table tdetl; + drop table tmain; + + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From c0ec1dad74b3045c88ffc68eee55230284f7ecc4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 20 Jun 2025 22:11:35 +0300 Subject: [PATCH 0573/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_default_fk_fields.py: Checked on 6.0.0.838; 3.0.13.33813. --- ...test_restrictions_for_default_fk_fields.py | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py diff --git a/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py b/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py new file mode 100644 index 00000000..e3504cc3 --- /dev/null +++ b/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py @@ -0,0 +1,217 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: FK definition: SET DEFAULT clause should not lead FK-columns to have their default values if parent record not exists or was removed +DESCRIPTION: + Single- and multi-segmented PK/UK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set autoddl off; + set list on; + + create domain dm_int_default int default -9999; + + -- case-1: single segment UK + -- ------------------------- + recreate table tmain_single_uk(id int unique using index tmain_pk); + recreate table tdetl_single_uk( + id int generated by default as identity + ,fk_id dm_int_default + ,constraint tdetl_fk foreign key(fk_id) references tmain_single_uk(id) + ON UPDATE SET DEFAULT + ON DELETE SET DEFAULT + ); + commit; + insert into tmain_single_uk(id) values(1111); + insert into tdetl_single_uk(fk_id) values(1111); + commit; + + -- Update existsing record in parent which have references from detail. + -- Must PASS because new value of ID equals to DEFAULT value for domain on which FK column is based: + update tmain_single_uk set id = -9999; + select * from tdetl_single_uk; + rollback; + + -- Add record so that both 1111 and -9999 now exists in the parent table: + insert into tmain_single_uk(id) values(-9999); + -- must PASS because default value now exists in just inserted record. + -- New value tdetl_single_uk.fk_id must become -9999: + delete from tmain_single_uk where id = 1111; + select * from tdetl_single_uk; + rollback; + + -- Must fail because 'set default' cause FK column to have value = -9999 that not exists in the parent table: + -- Statement failed, SQLSTATE = 23000 + -- violation of FOREIGN KEY constraint TDETL_FK on table TDETL_SINGLE_UK + -- -Foreign key reference target does not exist + -- -Problematic key value is (FK_ID = -9999) + update tmain_single_uk set id = -8888; + rollback; + + -- Must fail because 'set default' cause FK column to have value = -9999 that not exists in the parent table: + -- Statement failed, SQLSTATE = 23000 + -- violation of FOREIGN KEY constraint TDETL_FK on table TDETL_SINGLE_UK + -- -Foreign key reference target does not exist + -- -Problematic key value is (FK_ID = -9999) + delete from tmain_single_uk; + commit; + drop table tdetl_single_uk; + drop table tmain_single_uk; + + --############################## + + + -- case-2: multi segment UK + -- ------------------------- + recreate table tmain_multi_uk(id1 int, id2 int, unique(id1, id2) using index tmain_uk); + recreate table tdetl_multi_uk( + id int generated by default as identity + ,fk_id1 dm_int_default + ,fk_id2 dm_int_default + ,constraint tdetl_multi_fk foreign key(fk_id1, fk_id2) references tmain_multi_uk(id1, id2) + ON UPDATE SET DEFAULT + ON DELETE SET DEFAULT + ); + commit; + insert into tmain_multi_uk(id1, id2) values(1111, 2222); + insert into tdetl_multi_uk(fk_id1, fk_id2) values(1111, 2222); + commit; + + + -- Update existsing record in parent which have references from detail. + -- Must PASS because new value for ID1 and ID2 equals to DEFAULT value for domain on which FK columns are based: + update tmain_multi_uk set id1 = -9999, id2 = -9999; + select * from tdetl_multi_uk; + rollback; + + + insert into tmain_multi_uk(id1, id2) values(-9999, -9999); + delete from tmain_multi_uk where id1 = 1111 and id2 = 2222; + select * from tdetl_multi_uk; + rollback; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++ + -- Following three statements fail with same messages (all with SQLSTATE = 23000): + -- violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -- -Foreign key references are >>> present <<< for the record + -- -Problematic key value is (ID1 = 1111, ID2 = 2222) + update tmain_multi_uk set id2 = null; + update tmain_multi_uk set id1 = null; + update tmain_multi_uk set id1 = null, id2 = null; + + + -- Following three statements fail with same messages (all with SQLSTATE = 23000): + -- violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -- -Foreign key reference >>> target <<< does not exist + -- -Problematic key value is (FK_ID1 = -9999, FK_ID2 = -9999) + -- -At trigger CHECK_* + update tmain_multi_uk set id1 = 3333, id2 = null; + update tmain_multi_uk set id1 = null, id2 = 4444; + update tmain_multi_uk set id1 = 2222, id2 = 1111; + """ + + expected_stdout = """ + ID 1 + FK_ID -9999 + + ID 1 + FK_ID -9999 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL_SINGLE_UK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID = -9999) + -At trigger CHECK_1 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL_SINGLE_UK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID = -9999) + -At trigger CHECK_2 + + + ID 1 + FK_ID1 -9999 + FK_ID2 -9999 + + ID 1 + FK_ID1 -9999 + FK_ID2 -9999 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = -9999, FK_ID2 = -9999) + -At trigger CHECK_3 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = -9999, FK_ID2 = -9999) + -At trigger CHECK_3 + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = -9999, FK_ID2 = -9999) + -At trigger CHECK_3 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From d7004bbd9bc7b311563e941df4e703c82a943033 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 20 Jun 2025 22:11:48 +0300 Subject: [PATCH 0574/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_not_null_fk_fields.py: Checked on 6.0.0.838; 3.0.13.33813. --- ...est_restrictions_for_not_null_fk_fields.py | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py diff --git a/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py b/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py new file mode 100644 index 00000000..d3bb66df --- /dev/null +++ b/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py @@ -0,0 +1,203 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: FK definition: SET NULL clause should not lead FK-columns to have NULLs if parent record not exists or was removed +DESCRIPTION: + Single- and multi-segmented PK/UK are checked. + Work within a single transaction. +NOTES: + [17.06.2025] pzotov + 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. + ::: NB ::: + File act.files_dir/'test_config.ini' must contain section: + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). + + Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which + eventually will be like this: + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + 2. Adjusted expected output: removed single quotes from DB object name(s). + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set autoddl off; + set list on; + + create domain dm_int_not_null int NOT NULL; + + -- case-1: single segment UK + -- ------------------------- + recreate table tmain_single_uk(id int unique using index tmain_uk); + recreate table tdetl_single_uk( + id int generated by default as identity + ,fk_id dm_int_not_null + ,constraint tdetl_fk foreign key(fk_id) references tmain_single_uk(id) + ON UPDATE SET NULL + ON DELETE SET NULL + ); + commit; + insert into tmain_single_uk(id) values(1111); + insert into tdetl_single_uk(fk_id) values(1111); + commit; + + -- Fails with: + -- SQLSTATE = 23000 / violation of FOREIGN KEY ... / Foreign key references are present / Problematic key value is (ID = 1111) + -- ::: NB ::: + -- Behaviour here same as "ON UPDATE NO ACTION". Check for 'not null' (defined in domain) not occurs. + update tmain_single_uk set id = null; + rollback; + + insert into tmain_single_uk(id) values(null); + -- Must fail with: + -- Statement failed, SQLSTATE = 23000 + -- validation error for column TDETL_SINGLE_UK.FK_ID, value *** null *** + -- At trigger CHECK_* + delete from tmain_single_uk where id = 1111; + rollback; + + -- Fails with: + -- Statement failed, SQLSTATE = 23000 + -- validation error for column TDETL_SINGLE_UK.FK_ID, value *** null *** + -- -At trigger CHECK_* + delete from tmain_single_uk; + commit; + drop table tdetl_single_uk; + drop table tmain_single_uk; + + --############################## + + -- case-2: multi segment UK + -- ------------------------- + recreate table tmain_multi_uk(id1 int, id2 int, unique(id1, id2) using index tmain_uk); + recreate table tdetl_multi_uk( + id int generated by default as identity + ,fk_id1 dm_int_not_null + ,fk_id2 dm_int_not_null + ,constraint tdetl_multi_fk foreign key(fk_id1, fk_id2) references tmain_multi_uk(id1, id2) + ON UPDATE SET NULL + ON DELETE SET NULL + ); + commit; + insert into tmain_multi_uk(id1, id2) values(1111, 2222); + insert into tdetl_multi_uk(fk_id1, fk_id2) values(1111, 2222); + commit; + + --+++++++++++++++++++++++++++++++++++++++++++++++++++ + -- Following three statements fail with same messages (all with SQLSTATE = 23000): + -- violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -- -Foreign key references are present for the record + -- -Problematic key value is (ID1 = 1111, ID2 = 2222) + -- ::: NB ::: + -- Behaviour here same as "ON UPDATE NO ACTION". Check for 'not null' (defined in domain) not occurs. + update tmain_multi_uk set id2 = null; + update tmain_multi_uk set id1 = null; + update tmain_multi_uk set id1 = null, id2 = null; + --+++++++++++++++++++++++++++++++++++++++++++++++++++ + -- Following three statements fail with same messages (all with SQLSTATE = 23000): + -- Statement failed, SQLSTATE = 23000 + -- validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -- -At trigger CHECK_* + update tmain_multi_uk set id1 = 3333, id2 = null; + update tmain_multi_uk set id1 = null, id2 = 4444; + update tmain_multi_uk set id1 = 2222, id2 = 1111; + + rollback; + + -- Add record such that its columns not distinct from the pair of default values (defined for FK). + insert into tmain_multi_uk(id1, id2) values(null, null); + -- Now we try to remove record which currently is parent (id1 = 1111, id2 = 2222): + -- Following statement must cause violation of domain check expression and fail with SQLSTATE = 23000: + -- validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -- -At trigger CHECK_* + delete from tmain_multi_uk where id1 = 1111 and id2 = 2222; + rollback; + + -- Following statement must cause violation of domain check expression and fail with SQLSTATE = 23000: + -- validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -- -At trigger CHECK_* + delete from tmain_multi_uk; + commit; + drop table tdetl_multi_uk; + drop table tmain_multi_uk; + """ + + expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL_SINGLE_UK + -Foreign key references are present for the record + -Problematic key value is (ID = 1111) + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_SINGLE_UK.FK_ID, value *** null *** + -At trigger CHECK_2 + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_SINGLE_UK.FK_ID, value *** null *** + -At trigger CHECK_2 + + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_UK + -Foreign key references are present for the record + -Problematic key value is (ID1 = 1111, ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -At trigger CHECK_3 + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -At trigger CHECK_3 + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -At trigger CHECK_3 + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -At trigger CHECK_4 + + Statement failed, SQLSTATE = 23000 + validation error for column TDETL_MULTI_UK.FK_ID1, value *** null *** + -At trigger CHECK_4 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From ae4b806080037234dfb6b65264feb641cfcad2a1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:10:01 +0300 Subject: [PATCH 0575/1064] Added README.substitutions.md in order to refer to its content in all tests which need to be changed because of SQL schemas introducing. --- README.substitutions.md | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 README.substitutions.md diff --git a/README.substitutions.md b/README.substitutions.md new file mode 100644 index 00000000..92c24007 --- /dev/null +++ b/README.substitutions.md @@ -0,0 +1,43 @@ +Since 6.0.0.834 SQL schemas were intruduced in Firebird DBMS (commit: b8be591c0f9e1811f47fac792c8dd2f10c4cea28). +Following changes did appear since that snapshot: + * every DB object name that must be shown by test output now has prefix if its schema, with default name `"PUBLIC"`; + * the displayed object names become enclosed in double quotes, even if they are ascii-only and without inner spaces, e.g. `"ID"` etc; + * there is no ability to remove PUBLIC schema (to suppress its output); +Because of that, many tests needed to be re-implemented in order to make them pass on all checked FB (3.x ... 6.x and future versions). + +In order to reduce volume of this job and to avoid separation of expected values (depending on whether major version is 6.x or prior), +every such test has to be changed as follows: + * initiate 'substitutions' variable with list of tuples that were needed before (or make it empty, but anyway it must be created), + e.g.: + ``` + substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] + ``` + or + ``` + substitutions = [] + ``` + * append to this list pre-defined values from EXTERNAL file `act.files_dir/test_config.ini` as show below: + ``` + addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] + addi_subst_tokens = addi_subst_settings['addi_subst'] + for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + ``` + * NOTE. + File `act.files_dir/test_config.ini` must exist in the `$QA_HOME/files/` directory. + Content of this file is used in `$QA_HOME/firebird-qa/src/firebird/qa/plugin.py`, see QA_GLOBALS dictionary in its source. + Among other sections, following must present in this file: + ``` + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + ``` + If another schema will appear, e.g. "SYSTEM", and we need to suppress its output then `addi_subst` must be changed like this: + ``` + addi_subst="PUBLIC". "SYSTEM". " ' + ``` + + Applying of tokens from 'addi_subst' parameter to the 'substitutions' will lead to: + ``` + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + ``` +After this, every single/double quotes along with schema prefix(es) will be removed from DB object names in the test output. From 140da9e6bdee23332370d6d1c69feb56c5009091 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:21:36 +0300 Subject: [PATCH 0576/1064] Changed LF to CRLF because of lost format after push to github. --- README.substitutions.md | 86 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/README.substitutions.md b/README.substitutions.md index 92c24007..465e3dfc 100644 --- a/README.substitutions.md +++ b/README.substitutions.md @@ -1,43 +1,43 @@ -Since 6.0.0.834 SQL schemas were intruduced in Firebird DBMS (commit: b8be591c0f9e1811f47fac792c8dd2f10c4cea28). -Following changes did appear since that snapshot: - * every DB object name that must be shown by test output now has prefix if its schema, with default name `"PUBLIC"`; - * the displayed object names become enclosed in double quotes, even if they are ascii-only and without inner spaces, e.g. `"ID"` etc; - * there is no ability to remove PUBLIC schema (to suppress its output); -Because of that, many tests needed to be re-implemented in order to make them pass on all checked FB (3.x ... 6.x and future versions). - -In order to reduce volume of this job and to avoid separation of expected values (depending on whether major version is 6.x or prior), -every such test has to be changed as follows: - * initiate 'substitutions' variable with list of tuples that were needed before (or make it empty, but anyway it must be created), - e.g.: - ``` - substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] - ``` - or - ``` - substitutions = [] - ``` - * append to this list pre-defined values from EXTERNAL file `act.files_dir/test_config.ini` as show below: - ``` - addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] - addi_subst_tokens = addi_subst_settings['addi_subst'] - for p in addi_subst_tokens.split(): - substitutions.append( (p, '') ) - ``` - * NOTE. - File `act.files_dir/test_config.ini` must exist in the `$QA_HOME/files/` directory. - Content of this file is used in `$QA_HOME/firebird-qa/src/firebird/qa/plugin.py`, see QA_GLOBALS dictionary in its source. - Among other sections, following must present in this file: - ``` - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - ``` - If another schema will appear, e.g. "SYSTEM", and we need to suppress its output then `addi_subst` must be changed like this: - ``` - addi_subst="PUBLIC". "SYSTEM". " ' - ``` - - Applying of tokens from 'addi_subst' parameter to the 'substitutions' will lead to: - ``` - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - ``` -After this, every single/double quotes along with schema prefix(es) will be removed from DB object names in the test output. +Since 6.0.0.834 SQL schemas were intruduced in Firebird DBMS (commit: b8be591c0f9e1811f47fac792c8dd2f10c4cea28). +Following changes did appear since that snapshot: + * every DB object name that must be shown by test output now has prefix if its schema, with default name `"PUBLIC"`; + * the displayed object names become enclosed in double quotes, even if they are ascii-only and without inner spaces, e.g. `"ID"` etc; + * there is no ability to remove PUBLIC schema (to suppress its output); +Because of that, many tests needed to be re-implemented in order to make them pass on all checked FB (3.x ... 6.x and future versions). + +In order to reduce volume of this job and to avoid separation of expected values (depending on whether major version is 6.x or prior), +every such test has to be changed as follows: + * initiate 'substitutions' variable with list of tuples that were needed before (or make it empty, but anyway it must be created), + e.g.: + ``` + substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] + ``` + or + ``` + substitutions = [] + ``` + * append to this list pre-defined values from EXTERNAL file `act.files_dir/test_config.ini` as show below: + ``` + addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] + addi_subst_tokens = addi_subst_settings['addi_subst'] + for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + ``` + * NOTE. + File `act.files_dir/test_config.ini` must exist in the `$QA_HOME/files/` directory. + Content of this file is used in `$QA_HOME/firebird-qa/src/firebird/qa/plugin.py`, see QA_GLOBALS dictionary in its source. + Among other sections, following must present in this file: + ``` + [schema_n_quotes_suppress] + addi_subst="PUBLIC". " ' + ``` + If another schema will appear, e.g. "SYSTEM", and we need to suppress its output then `addi_subst` must be changed like this: + ``` + addi_subst="PUBLIC". "SYSTEM". " ' + ``` + + Applying of tokens from 'addi_subst' parameter to the 'substitutions' will chage it to follwing: + ``` + substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] + ``` +After this, every single/double quotes along with schema prefix(es) will be removed from DB object names in the test output. From 7d439a1e566288ce06eb952c68473d724a2f578f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:36:35 +0300 Subject: [PATCH 0577/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_default_fk_fields.py: test_restrictions_for_default_fk_fields.py Adjusted title. Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- ...test_restrictions_for_default_fk_fields.py | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py b/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py index e3504cc3..64d77545 100644 --- a/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py +++ b/tests/functional/fkey/common/test_restrictions_for_default_fk_fields.py @@ -2,23 +2,17 @@ """ ID: n/a -TITLE: FK definition: SET DEFAULT clause should not lead FK-columns to have their default values if parent record not exists or was removed +TITLE: FK definition: SET DEFAULT clause should not lead FK-columns to have their default values if parent record not yet exists or was removed DESCRIPTION: - Single- and multi-segmented PK/UK are checked. + Parent table has UNIQUE constraint declared for NULLABLE column(s). + Child table has column(s) on which FK is declared, with options: ON UPDATE SET DEFAULT and ON DELETE SET DEFAULT. + Single- and multi-segmented unique keys are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. @@ -99,7 +93,6 @@ def test_1(act: Action): --############################## - -- case-2: multi segment UK -- ------------------------- recreate table tmain_multi_uk(id1 int, id2 int, unique(id1, id2) using index tmain_uk); From 2cbe373202dd1a808b5973d6619325c193408c2e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:48:43 +0300 Subject: [PATCH 0578/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_not_null_fk_fields.py: Adjusted title. Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- ...est_restrictions_for_not_null_fk_fields.py | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py b/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py index d3bb66df..ba2230cc 100644 --- a/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py +++ b/tests/functional/fkey/common/test_restrictions_for_not_null_fk_fields.py @@ -2,23 +2,17 @@ """ ID: n/a -TITLE: FK definition: SET NULL clause should not lead FK-columns to have NULLs if parent record not exists or was removed +TITLE: FK definition: SET NULL clause should not lead FK-columns to have NULLs. DESCRIPTION: + Parent table has UNIQUE constraint declared for NULLABLE column(s). + Child table has column(s) on which FK is declared, with options: ON UPDATE SET NULL and ON DELETE SET NULL. Single- and multi-segmented PK/UK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From aaee9b9ba70e4de346d5b377bd763a1a0d12f1dc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:50:03 +0300 Subject: [PATCH 0579/1064] Added/Updated tests\functional\fkey\common\test_restrictions_for_diff_table_types.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_restrictions_for_diff_table_types.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py b/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py index 315a2dd1..06fb24b4 100644 --- a/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py +++ b/tests/functional/fkey/common/test_restrictions_for_diff_table_types.py @@ -9,19 +9,11 @@ * A connection-bound ("PRESERVE ROWS") GTT cannot reference a transaction-bound ("DELETE ROWS") GTT Work within a single attachment. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). - 3. See doc: + [21.06.2025] pzotov + 1. ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + 2. See doc: https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html#fblangref50-ddl-tbl-gtt-restrictions Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") From 6e660e93ded9a1d232e401d8d2940d082e7f7207 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:50:56 +0300 Subject: [PATCH 0580/1064] Added/Updated tests\functional\fkey\common\test_prohibit_change_of_key_column_types.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_prohibit_change_of_key_column_types.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py b/tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py index 3953fec0..cad11736 100644 --- a/tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py +++ b/tests/functional/fkey/common/test_prohibit_change_of_key_column_types.py @@ -7,18 +7,10 @@ Single- and multi-segmented PK/UK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 96aba86a6cf8afd3d4244e623e2664cda6bffe4f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:54:13 +0300 Subject: [PATCH 0581/1064] Added/Updated tests\functional\fkey\cascade\test_master_uk_update_if_no_cascade.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_master_uk_update_if_no_cascade.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py index fd3eedfe..7c095de9 100644 --- a/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_uk_update_if_no_cascade.py @@ -9,18 +9,10 @@ Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 115b656ef7a660006056bea546840b66c587b1ea Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:55:16 +0300 Subject: [PATCH 0582/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_delete_if_no_cascade.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_master_pk_delete_if_no_cascade.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py index bce833a0..3321b082 100644 --- a/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_delete_if_no_cascade.py @@ -9,18 +9,10 @@ Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 21a9e804610d4649da1934835748daa687befd3c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:55:46 +0300 Subject: [PATCH 0583/1064] Added/Updated tests\functional\fkey\cascade\test_master_uk_delete_if_no_cascade.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_master_uk_delete_if_no_cascade.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py index 978f6412..0fe0d9fa 100644 --- a/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_uk_delete_if_no_cascade.py @@ -9,18 +9,10 @@ Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From f617c3dfbad43a2ab431f4ea540cc9d04658ded5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:56:11 +0300 Subject: [PATCH 0584/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_update_if_no_cascade.py: Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_master_pk_update_if_no_cascade.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py index 13bc6506..a38ef6c7 100644 --- a/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_update_if_no_cascade.py @@ -9,18 +9,10 @@ Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 6f202fbd8be5405443965fc082cb6470d6548d90 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:59:33 +0300 Subject: [PATCH 0585/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_on_delete_cascade.py: Adjusted title and description. Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../fkey/cascade/test_master_pk_on_delete_cascade.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py index e7afe3a7..a731bb97 100644 --- a/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py @@ -2,9 +2,11 @@ """ ID: n/a -TITLE: Deleting record in master must cause deletions in appropriate detail if 'ON DELETE CASCADE' option is used +TITLE: Deleting record in master must cause deletions in appropriate detail if FK references to PK and 'ON DELETE CASCADE' option is used. DESCRIPTION: Test verifies RI mechanism when ON DELETE CASCADE option is used. + Parent table has PRIMARY KEY constraint. + Child table has column(s) on which FK is declared, with option ON DELETE CASCADE. Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: From 94310b25fe7ec7273affad3232d0384239c78ecc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 00:59:54 +0300 Subject: [PATCH 0586/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_on_delete_cascade.py: Adjusted title and description. Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../cascade/test_master_pk_on_delete_cascade.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py index a731bb97..2c1fbc07 100644 --- a/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_on_delete_cascade.py @@ -10,18 +10,10 @@ Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 099803ec3dc939a60ac2c47627ec56c6b334fe8b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 01:01:31 +0300 Subject: [PATCH 0587/1064] Added/Updated tests\functional\fkey\cascade\test_master_pk_on_update_cascade.py: Adjusted title and description. Replaced notes about suppressing schema and quotes with path '$QA_HOME/README.substitutions.md' and appropriate URL in GH repo. --- .../test_master_pk_on_update_cascade.py | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py b/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py index 4d7342ce..61d17f98 100644 --- a/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py +++ b/tests/functional/fkey/cascade/test_master_pk_on_update_cascade.py @@ -2,24 +2,18 @@ """ ID: n/a -TITLE: Updating PK column(s) in master must cause changes in appropriate detail column(s) if 'ON UPDATE CASCADE' option is used +TITLE: Updating PK column(s) in master must cause changes in appropriate detail column(s) if FK references to PK and 'ON UPDATE CASCADE' option is used DESCRIPTION: Test verifies RI mechanism when ON UPDATE CASCADE option is used: updating record in master should cause appropriate updates in detail. + Parent table has PRIMARY KEY constraint. + Child table has column(s) on which FK is declared, with option ON UPDATE CASCADE. Single- and multi-segmented PK/FK are checked. Work within a single transaction. NOTES: - [17.06.2025] pzotov - 1. Extended 'subsitutions' list is used here to suppress "PUBLIC" schema prefix and remove single/double quotes from all object names. Need since 6.0.0.834. - ::: NB ::: - File act.files_dir/'test_config.ini' must contain section: - [schema_n_quotes_suppress] - addi_subst="PUBLIC". " ' - (this file is used in qa/plugin.py, see QA_GLOBALS dictionary). - - Value of parameter 'addi_subst' is splitted on tokens using space character and we add every token to 'substitutions' list which - eventually will be like this: - substitutions = [ ( , ('"PUBLIC".', ''), ('"', ''), ("'", '') ] - 2. Adjusted expected output: removed single quotes from DB object name(s). + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") Checked on 6.0.0.838; 3.0.13.33813. From 4eb4185f848f6da528c16068a6e086a31fe8ac7f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 02:14:42 +0300 Subject: [PATCH 0588/1064] Added/Updated tests\functional\fkey\common\test_non_priv_user_access_to_child_for_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- ...n_priv_user_access_to_child_for_cascade.py | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 tests/functional/fkey/common/test_non_priv_user_access_to_child_for_cascade.py diff --git a/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_cascade.py b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_cascade.py new file mode 100644 index 00000000..d9cccce6 --- /dev/null +++ b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_cascade.py @@ -0,0 +1,119 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Child table must be updated even if current user has no privileges on it but 'CASCADE' present in FK declaration. +DESCRIPTION: + Child table has column(s) on which FK is declared, with options: ON UPDATE CASCADE and ON DELETE CASCADE. + Work within a single transaction. +NOTES: + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +init_sql = """ + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl( + id int generated by default as identity + ,pid int + ,constraint tdetl_fk foreign key(pid) references tmain(id) + ON DELETE CASCADE + ON UPDATE CASCADE + ); + commit; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db', substitutions = substitutions) + +tmp_user = user_factory('db', name='tmp_parent_only_accessor', password='123') + +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User): + + test_sql = f""" + set bail OFF; + set wng off; + set list on; + -- set echo on; + revoke all on all from {tmp_user.name}; + grant select, insert, update, delete on tmain to {tmp_user.name}; + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + select current_user as whoami from rdb$database; + + -- Update existsing record in parent which have references from detail. + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + -- New value in tdetl.pid will be -9999: + update tmain set id = -9999; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-1' as msg from rdb$database; + set count on; + select m.id as tmain_pk from tmain m; + select d.id as tdetl_pk, d.pid as tdetl_pid from tdetl d; + set count off; + + delete from tdetl; + delete from tmain; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + -- Record in tdetl.pid will be DELETED: + delete from tmain where id = 1111; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-2' as msg from rdb$database; + set count on; + select m.id as tmain_pk from tmain m; + select d.id as tdetl_pk, d.pid as tdetl_pid from tdetl d; + set count off; + """ + + expected_stdout = f""" + WHOAMI {tmp_user.name.upper()} + + MSG point-1 + TMAIN_PK -9999 + Records affected: 1 + + TDETL_PK 1 + TDETL_PID -9999 + Records affected: 1 + + MSG point-2 + Records affected: 0 + Records affected: 0 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From f7fcc29767437d4451673c41b5bab594ee3c1e8f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 02:14:57 +0300 Subject: [PATCH 0589/1064] Added/Updated tests\functional\fkey\common\test_non_priv_user_access_to_child_for_set_null.py: Checked on 6.0.0.838; 3.0.13.33813. --- ..._priv_user_access_to_child_for_set_null.py | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_null.py diff --git a/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_null.py b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_null.py new file mode 100644 index 00000000..0d79d695 --- /dev/null +++ b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_null.py @@ -0,0 +1,123 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Child table must be updated even if current user has no privileges on it but 'SET NULL' present in FK declaration. +DESCRIPTION: + Child table has column(s) on which FK is declared, with options: ON UPDATE SET NULL and ON DELETE SET NULL. + Work within a single transaction. +NOTES: + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +init_sql = """ + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl( + id int generated by default as identity + ,pid int + ,constraint tdetl_fk foreign key(pid) references tmain(id) + ON DELETE SET NULL + ON UPDATE SET NULL + ); + commit; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db', substitutions = substitutions) + +tmp_user = user_factory('db', name='tmp_parent_only_accessor', password='123') + +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User): + + test_sql = f""" + set bail OFF; + set wng off; + set list on; + -- set echo on; + revoke all on all from {tmp_user.name}; + grant select, insert, update, delete on tmain to {tmp_user.name}; + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + select current_user as whoami from rdb$database; + + -- Update existsing record in parent which have references from detail. + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + -- New value in tdetl.pid will be NULL: + update tmain set id = -9999; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-1' as msg from rdb$database; + set count on; + select m.id as tmain_pk from tmain m; + select d.id as tdetl_pk, d.pid as tdetl_pid from tdetl d; + set count off; + + delete from tdetl; + delete from tmain; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + -- New value in tdetl.pid will be NULL: + delete from tmain where id = 1111; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-2' as msg from rdb$database; + set count on; + select m.id as tmain_pk from tmain m; + select d.id as tdetl_pk, d.pid as tdetl_pid from tdetl d; + set count off; + """ + + expected_stdout = f""" + WHOAMI {tmp_user.name.upper()} + MSG point-1 + + TMAIN_PK -9999 + Records affected: 1 + + TDETL_PK 1 + TDETL_PID + Records affected: 1 + + MSG point-2 + + Records affected: 0 + + TDETL_PK 2 + TDETL_PID + Records affected: 1 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From c85777646b082b24231a15ebbc2a3dacacc86866 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 02:15:15 +0300 Subject: [PATCH 0590/1064] Added/Updated tests\functional\fkey\common\test_non_priv_user_access_to_child_for_set_default.py: test_non_priv_user_access_to_child_for_set_default.py Checked on 6.0.0.838; 3.0.13.33813. --- ...iv_user_access_to_child_for_set_default.py | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_default.py diff --git a/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_default.py b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_default.py new file mode 100644 index 00000000..9784cc74 --- /dev/null +++ b/tests/functional/fkey/common/test_non_priv_user_access_to_child_for_set_default.py @@ -0,0 +1,113 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Child table must be updated even if current user has no privileges on it but 'SET DEFAULT' present in FK declaration. +DESCRIPTION: + Child table has column(s) on which FK is declared, with options: ON UPDATE SET DEFAULT and ON DELETE SET DEFAULT. + Work within a single transaction. +NOTES: + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger\\s+\\S+', 'At trigger')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +init_sql = """ + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl( + id int generated by default as identity + ,pid int default -9999 + ,constraint tdetl_fk foreign key(pid) references tmain(id) + ON DELETE SET DEFAULT + ON UPDATE SET DEFAULT + ); + commit; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; +""" +db = db_factory(init = init_sql) +act = python_act('db', substitutions = substitutions) + +tmp_user = user_factory('db', name='tmp_parent_only_accessor', password='123') + +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User): + + test_sql = f""" + set bail OFF; + set wng off; + set list on; + -- set echo on; + revoke all on all from {tmp_user.name}; + grant select, insert, update, delete on tmain to {tmp_user.name}; + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + select current_user as whoami from rdb$database; + + -- Update existsing record in parent which have references from detail. + -- Must PASS because new value of ID equals to DEFAULT value for domain on which FK column is based. + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + update tmain set id = -9999; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-1' as msg, m.id as tmain_pk, d.id as tdetl_pk, d.pid as tdetl_pid from tmain m left join tdetl d on m.id = d.pid; + + delete from tdetl; + delete from tmain; + insert into tmain(id) values(1111); + insert into tdetl(pid) values(1111); + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + + -- Add record so that both 1111 and -9999 now exists in the parent table: + insert into tmain(id) values(-9999); + + -- must PASS because default value now exists in just inserted record. + -- New value tdetl.pid must become -9999. + -- NB: detail table WILL BE CHANGED despite that current user has no any privilege on this table. + delete from tmain where id = 1111; + commit; + + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; + select 'point-2' as msg, m.id as tmain_pk, d.id as tdetl_pk, d.pid as tdetl_pid from tmain m left join tdetl d on m.id = d.pid; + """ + + expected_stdout = f""" + WHOAMI {tmp_user.name.upper()} + + MSG point-1 + TMAIN_PK -9999 + TDETL_PK 1 + TDETL_PID -9999 + + MSG point-2 + TMAIN_PK -9999 + TDETL_PK 2 + TDETL_PID -9999 + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From f6fe2fd4e4c3ba2d3f190a4788b1c767bcca65bd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 11:13:33 +0300 Subject: [PATCH 0591/1064] Added/Updated tests\functional\fkey\cascade\test_detail_upsert_if_no_cascade.py: Checked on 6.0.0.838; 3.0.13.33813. --- .../test_detail_upsert_if_no_cascade.py | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py diff --git a/tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py b/tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py new file mode 100644 index 00000000..fdc34753 --- /dev/null +++ b/tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py @@ -0,0 +1,181 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: FK-columns columns in the child table must either all be equal to appropriate columns in the parent or some/all of them must be null +DESCRIPTION: + Single- and multi-segmented FK are checked. + Work within a single transaction. +NOTES: + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +expected_stdout = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key reference target does not exist + -Problematic key value is (PID = 2) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_FK on table TDETL + -Foreign key reference target does not exist + -Problematic key value is (PID = 2) + + TDETL_ID 100 + TDETL_PID + TDETL_ID 101 + TDETL_PID 1 + Records affected: 2 + + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 3333, FK_ID2 = 4444) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 3333, FK_ID2 = 2222) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 1111, FK_ID2 = 3333) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 3333, FK_ID2 = 1111) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 3333, FK_ID2 = 3333) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 9999, FK_ID2 = 3333) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint TDETL_MULTI_FK on table TDETL_MULTI_FK + -Foreign key reference target does not exist + -Problematic key value is (FK_ID1 = 3333, FK_ID2 = 9999) + + TDETL_MULTI_ID 1 + TDETL_MULTI_FK1 + TDETL_MULTI_FK2 2222 + TDETL_MULTI_ID 2 + TDETL_MULTI_FK1 + TDETL_MULTI_FK2 2222 + TDETL_MULTI_ID 3 + TDETL_MULTI_FK1 1111 + TDETL_MULTI_FK2 + TDETL_MULTI_ID 4 + TDETL_MULTI_FK1 1111 + TDETL_MULTI_FK2 2222 + TDETL_MULTI_ID 5 + TDETL_MULTI_FK1 + TDETL_MULTI_FK2 7777 + TDETL_MULTI_ID 6 + TDETL_MULTI_FK1 8888 + TDETL_MULTI_FK2 + Records affected: 6 + +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = """ + set bail OFF; + set list on; + + -- case-1: single segment UK/FK: + -- +++++++++++++++++++++++++++++ + recreate table tmain(id int unique using index tmain_uk); + recreate table tdetl(id int unique using index tdetl_uk, pid int, constraint tdetl_fk foreign key(pid) references tmain(id)); + insert into tmain(id) values(1); + insert into tdetl(id, pid) values(100, 1); -- must PASS + insert into tdetl(id, pid) values(101, null); -- must PASS + insert into tdetl(id, pid) values(102, 2); -- must FAIL // no record in tmain with ID = 2 + update tdetl set pid = 2 where id = 101; -- must FAIL // no record in tmain with ID = 2 + update tdetl set pid = 1 where id = 101; -- must PASS + update tdetl set pid = null where id = 100; -- must PASS + set count on; + select d.id as tdetl_id, d.pid as tdetl_pid from tdetl d order by d.id; + set count off; + commit; + drop table tdetl; + drop table tmain; + -------------------------------------------- + + -- case-2: multi segment UK/FK: + -- ++++++++++++++++++++++++++++ + recreate table tmain_multi_uk(id1 int, id2 int, unique(id1, id2) using index tmain_uk); + recreate table tdetl_multi_fk( + id int generated by default as identity + ,fk_id1 int + ,fk_id2 int + ,constraint tdetl_multi_fk foreign key(fk_id1, fk_id2) references tmain_multi_uk(id1, id2) + ); + commit; + insert into tmain_multi_uk(id1, id2) values(1111, 2222); + -- following six statements must PASS. First because of full match FK to parent UK, others because of nulls: + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(1,1111, 2222); + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(2,1111, null); + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(3,null, 1111); + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(4,null, null); + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(5,9999, null); + insert into tdetl_multi_fk(id, fk_id1, fk_id2) values(6,null, 9999); + + insert into tdetl_multi_fk(id,fk_id1, fk_id2) values(7,3333, 4444); -- must FAIL // no record in parent with (id1,id2) = (3333, 4444) + + -- Following must FAIL // no record in parent with appropriate UK which have not-null values + update tdetl_multi_fk set fk_id1 = 3333 where id = 1; + update tdetl_multi_fk set fk_id2 = 3333 where id = 2; + update tdetl_multi_fk set fk_id1 = 3333 where id = 3; + update tdetl_multi_fk set fk_id1 = 3333, fk_id2 = 3333 where id = 4; + update tdetl_multi_fk set fk_id2 = 3333 where id = 5; + update tdetl_multi_fk set fk_id1 = 3333 where id = 6; + + -- must PASS: we use null in at least one column values: + update tdetl_multi_fk set fk_id1 = null where id = 1; + update tdetl_multi_fk set fk_id1 = null, fk_id2 = 2222 where id = 2; + update tdetl_multi_fk set fk_id1 = 1111, fk_id2 = null where id = 3; + update tdetl_multi_fk set fk_id1 = 1111, fk_id2 = 2222 where id = 4; -- match to parent key + update tdetl_multi_fk set fk_id1 = null, fk_id2 = 7777 where id = 5; + update tdetl_multi_fk set fk_id1 = 8888, fk_id2 = null where id = 6; + set count on; + select d.id as tdetl_multi_id, d.fk_id1 as tdetl_multi_fk1, d.fk_id2 as tdetl_multi_fk2 from tdetl_multi_fk d order by d.id; + set count off; + commit; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout From 35de53fd2706475f8c3d20d0756b3d284b18e4ad Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 21 Jun 2025 11:16:34 +0300 Subject: [PATCH 0592/1064] Moved to suitable folder, renamed --- .../test_dml_in_detail_if_no_parent_exists.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/functional/fkey/{cascade/test_detail_upsert_if_no_cascade.py => common/test_dml_in_detail_if_no_parent_exists.py} (100%) diff --git a/tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py b/tests/functional/fkey/common/test_dml_in_detail_if_no_parent_exists.py similarity index 100% rename from tests/functional/fkey/cascade/test_detail_upsert_if_no_cascade.py rename to tests/functional/fkey/common/test_dml_in_detail_if_no_parent_exists.py From d6688f83300d2c5805f8da47bbb55828b93eb18c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 12:34:30 +0300 Subject: [PATCH 0593/1064] Added/Updated tests\functional\fkey\cascade\test_cascade_recursive_actions.py: Checked on 6.0.0.838; 3.0.13.33813. SEE NOTES. --- .../cascade/test_cascade_recursive_actions.py | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 tests/functional/fkey/cascade/test_cascade_recursive_actions.py diff --git a/tests/functional/fkey/cascade/test_cascade_recursive_actions.py b/tests/functional/fkey/cascade/test_cascade_recursive_actions.py new file mode 100644 index 00000000..9955b630 --- /dev/null +++ b/tests/functional/fkey/cascade/test_cascade_recursive_actions.py @@ -0,0 +1,191 @@ +#coding:utf-8 + +""" +ID: n/a +TITLE: Cyclic references between PK and FK (declared with 'ON ... CASCADE') must not cause infinite loop when records are deleted or updated in any of involved tables. +DESCRIPTION: + Test verifies RI mechanism when ON DELETE/UPDATE CASCADE option is used. + Three tables are created which have PK and FK, and refer to each other as follows: + T1 (id, fk3) <-- T2 (id, fk1) // "t1.id <-- t2.fk1" + T2 (id, fk1) <-- T3 (id, fk2) // "t2.id <-- t3.fk2" + T3 (id, fk2) <-- T1 (id, fk3) // "t3.id <-- t1.fk3" + One record with values = (1,1) is added to each table. + + Deletion of this record from t1 (or any other table) must finish w/o errors and all table must become empty. + + But "update t1 set id = id + 1;" will cause infinite loop and engine has to stop it. + One may see 'progress' of this loop by querying value of sequence 'g'. + ::: ACHTUNG ::: + Only FB 3.x detects this problem when GEN_ID = 1003 (i.e. after iteration N 1000) and raises: + Statement failed, SQLSTATE = 54001 + Too many concurrent executions of the same request + -At trigger 'CHECK_3' + At trigger 'CHECK_2' + At trigger 'CHECK_1' + At trigger 'CHECK_3' + ... + Other major versions (FB 4.x ... 6.x) will *hang*, without any CPU usage. + Interrupting of ISQL using Ctrl-Break will not release DB, one need to restart FB. + Values of GEN_ID will be different: + 4.0.6.3213: Generator G, current value: 2859 + 5.0.3.1666: Generator G, current value: 2334 + 6.0.0.838: Generator PUBLIC.G, current value: 2335 + Because of this, it was decided to limit number of iterations for update, see 'LIMIT_ITERATIONS_FOR_UPDATE' + (discussed with Vlad, letter 21.06.2025 15:01, subj: "#8598: how to check it ?") + + Only single segmented UK/FK are checked. + Work within a single transaction. +NOTES: + [21.06.2025] pzotov + ::: NB ::: + SQL schema name (6.x+), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Discussed with Vlad, letters 16.06.2025 13:54 (subj: "#8598: ...") + Checked on 6.0.0.838; 3.0.13.33813. +""" + +import pytest +from firebird.qa import * + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(): + substitutions.append( (p, '') ) + +db = db_factory() +act = python_act('db', substitutions = substitutions) + +# ::: ACHTUNG ::: +# Only FB3.x can detect infinite loop and interrupt it with raising +# "SQLSTATE = 54001 / Too many concurrent executions of the same request" +# FB 4.x ... 6.x will hang on update after ~2330 iterations. +# We have to limit number of iterations! +################################## +LIMIT_ITERATIONS_FOR_UPDATE = 2000 +################################## + +expected_stdout = """ + Records affected: 1 + Records affected: 0 + Records affected: 0 + Records affected: 0 + + Records affected: 1 + + ID 2003 + FK3 2005 + Records affected: 1 + + ID 2004 + FK1 2003 + Records affected: 1 + + ID 2005 + FK2 2004 + Records affected: 1 + + GEN_ID 2003 +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + test_sql = f""" + -- ################# + -- ON DELETE CASCADE + -- ################# + set bail off; + set list on; + create table t1 (id int unique, fk3 int default null); + create table t2 (id int unique, fk1 int references t1 (id) on delete cascade); + create table t3 (id int unique, fk2 int references t2 (id) on delete cascade); + commit; + + insert into t1(id, fk3) values(1, 1); + insert into t2(id, fk1) values(1, 1); + insert into t3(id, fk2) values(1, 1); + commit; + + alter table t1 add constraint t1_fk foreign key(fk3) references t3(id) on delete cascade; + commit; + + set bail off; + + set list on; + set count on; + + delete from t1; + select * from t1; + select * from t2; + select * from t3; + set count off; + commit; + alter table t1 drop constraint t1_fk; + drop table t3; + drop table t2; + drop table t1; + + -------------------------------------------- + -- ################# + -- ON UPDATE CASCADE + -- ################# + set bail on; + create sequence g; + create table t1 (id int unique, fk3 int default null); + create table t2 (id int unique, fk1 int references t1 (id) on update cascade); + create table t3 (id int unique, fk2 int references t2 (id) on update cascade); + commit; + + insert into t1(id, fk3) values(1, 1); + insert into t2(id, fk1) values(1, 1); + insert into t3(id, fk2) values(1, 1); + commit; + + alter table t1 add constraint t1_fk foreign key(fk3) references t3(id) on update cascade; + set term ^; + create trigger t1_bu for t1 before update as + begin + if (gen_id(g,0) > {LIMIT_ITERATIONS_FOR_UPDATE}) then + exit; + if (old.fk3 <> new.fk3) then + new.id = new.fk3 + 1 + 0*gen_id(g,1); + end + ^ + create trigger t2_bu for t2 before update as + begin + new.id = new.fk1 + 1 + 0*gen_id(g,1); + end + ^ + create trigger t3_bu for t3 before update as + begin + new.id = new.fk2 + 1 + 0*gen_id(g,1); + end + ^ + set term ;^ + commit; + set bail off; + set count on; + update t1 set id = id + 1; + select * from t1; + select * from t2; + select * from t3; + set count off; + select gen_id(g,0) from rdb$database; + commit; + alter table t1 drop constraint t1_fk; + drop table t3; + drop table t2; + drop table t1; + """ + + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], combine_output = True, input = test_sql) + + assert act.clean_stdout == act.clean_expected_stdout + \ No newline at end of file From 164462f50b8f6dd573e59abcc2789548f84029bc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 12:41:44 +0300 Subject: [PATCH 0594/1064] Added tokens to 'addi_subst' parameter in [schema_n_quotes_suppress] section --- files/test_config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/test_config.ini b/files/test_config.ini index 75519ebd..40ef118c 100644 --- a/files/test_config.ini +++ b/files/test_config.ini @@ -88,4 +88,4 @@ ARCHIVE_SUB_DIR = repl_archive RUN_SWEEP_AT_END = 0 [schema_n_quotes_suppress] -addi_subst="PUBLIC". " ' +addi_subst="PUBLIC". "SYSTEM". PUBLIC. SYSTEM. " ' From 088dffa06f69b1bbf470524077eabdd288a5fa9f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 17:06:31 +0300 Subject: [PATCH 0595/1064] Added/Updated tests\bugs\gh_8619_test.py: Checked on 6.0.0.853-c1954c4 --- tests/bugs/gh_8619_test.py | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/bugs/gh_8619_test.py diff --git a/tests/bugs/gh_8619_test.py b/tests/bugs/gh_8619_test.py new file mode 100644 index 00000000..e08962fa --- /dev/null +++ b/tests/bugs/gh_8619_test.py @@ -0,0 +1,51 @@ +#coding:utf-8 + +""" +ID: issue-8619 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8619 +TITLE: Regression in 6.0.0.653 ("Stack overflow. ... requirements of the runtime stack have exceeded the memory"). +DESCRIPTION: +NOTES: + [22.06.2025] pzotov + Checked on 6.0.0.853-c1954c4 +""" + +import pytest +from firebird.qa import * + +db = db_factory() + +test_script = """ + set list on; + recreate table test(id1 int, id2 int, id3 int, unique(id1, id2, id3)); + + -- ####################### + -- INSERT USING SELECT ... + -- ####################### + insert into test(id1, id2, id3) + with + a as ( + select 1000 as v from rdb$database union all + select 1000 as v from rdb$database union all + select null as v from rdb$database + ) + select distinct a1.v, a2.v, a3.v + from a a1 + cross join a a2 + cross join a a3 + ; + + select 1 from mon$database; +""" + +act = isql_act('db', test_script, substitutions = [('[\t ]+', ' ')]) + +expected_stdout = """ + CONSTANT 1 +""" + +@pytest.mark.version('>=6.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f6bbbf9522bcc1885e4a40b12d0cfa502601fbd7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:04:02 +0300 Subject: [PATCH 0596/1064] Added/Updated tests\bugs\core_0053_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 3.0.13.33813. --- tests/bugs/core_0053_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0053_test.py b/tests/bugs/core_0053_test.py index 2c981626..3a843dc2 100644 --- a/tests/bugs/core_0053_test.py +++ b/tests/bugs/core_0053_test.py @@ -25,6 +25,13 @@ reset like this: c = gen_id(g_gather_stat, -gen_id(g_gather_stat, 0)); JIRA: CORE-53 FBTEST: bugs.core_0053 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 3.0.13.33813. """ import pytest @@ -32,6 +39,16 @@ db = db_factory(from_backup='mon-stat-gathering-2_5.fbk') +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + test_script = """ set list on; @@ -118,7 +135,7 @@ -- on 2.5 = {5, 5}, on 3.0 = {5, 3} ==> ratio 3.00 should be always enough. """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ PLAN (T ORDER TEST_F1_F2) From 7312b726d73dfec22765b0cf75a121c314cad55d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:08:23 +0300 Subject: [PATCH 0597/1064] Added/Updated tests\bugs\core_0059_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0059_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0059_test.py b/tests/bugs/core_0059_test.py index ba86d9b6..564e94ec 100644 --- a/tests/bugs/core_0059_test.py +++ b/tests/bugs/core_0059_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-59 FBTEST: bugs.core_0059 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -23,7 +30,17 @@ insert into test default values; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stderr = """ Statement failed, SQLSTATE = 23000 From c5f2671fb4605c9ae47af3753ff78f3a1c286455 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:18:43 +0300 Subject: [PATCH 0598/1064] Added/Updated tests\bugs\core_0070_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0070_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0070_test.py b/tests/bugs/core_0070_test.py index ede9ff92..63d49905 100644 --- a/tests/bugs/core_0070_test.py +++ b/tests/bugs/core_0070_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-70 FBTEST: bugs.core_0070 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -26,7 +33,17 @@ select * from t1 where upper(col1) = '1'; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ PLAN (T1 INDEX (IDX1)) From c7d74fa8778d7a7695e66ef4475203306f7a5393 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:22:48 +0300 Subject: [PATCH 0599/1064] Added/Updated tests\bugs\core_0104_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0104_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0104_test.py b/tests/bugs/core_0104_test.py index b5f17378..38feb13c 100644 --- a/tests/bugs/core_0104_test.py +++ b/tests/bugs/core_0104_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-104 FBTEST: bugs.core_0104 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,7 +38,17 @@ commit; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', ''), ('INTEG_\\d+', 'INTEG') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stderr = """Statement failed, SQLSTATE = 23000 violation of PRIMARY or UNIQUE KEY constraint "INTEG_4" on table "TEST" From 666b031ce704d509a42ff8984b1f7251163a26e2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:24:09 +0300 Subject: [PATCH 0600/1064] Added/Updated tests\bugs\core_0115_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0115_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0115_test.py b/tests/bugs/core_0115_test.py index ca49dfd4..a91a0586 100644 --- a/tests/bugs/core_0115_test.py +++ b/tests/bugs/core_0115_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-115 FBTEST: bugs.core_0115 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -40,7 +47,17 @@ set count off; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ PLAN (TEST NATURAL) From ddad1a1b9db774d1b2a3b00a3b5caebb3394bb96 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:26:00 +0300 Subject: [PATCH 0601/1064] Added/Updated tests\bugs\core_0116_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0116_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0116_test.py b/tests/bugs/core_0116_test.py index c004e40c..e5d3a982 100644 --- a/tests/bugs/core_0116_test.py +++ b/tests/bugs/core_0116_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-116 FBTEST: bugs.core_0116 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -22,7 +29,17 @@ create table ext_log external file '$(DATABASE_LOCATION)z.dat' (F1 INT, F2 BLOB SUB_TYPE TEXT); """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stderr = """ Statement failed, SQLSTATE = HY004 From 8c5592b7e5074267a20e7e1b870e7d89a0390a9d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:28:02 +0300 Subject: [PATCH 0602/1064] Added/Updated tests\bugs\core_0166_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0166_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0166_test.py b/tests/bugs/core_0166_test.py index fa3c5eab..58e7c848 100644 --- a/tests/bugs/core_0166_test.py +++ b/tests/bugs/core_0166_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-166 FBTEST: bugs.core_0166 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -58,7 +65,17 @@ from company c order by c.id; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ ID 100 From 9e3057c6bb4393b0b5fc447a8d08dd8b650aec40 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 18:29:14 +0300 Subject: [PATCH 0603/1064] Added/Updated tests\bugs\core_0196_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0196_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0196_test.py b/tests/bugs/core_0196_test.py index 6f0b9e8f..e42257bb 100644 --- a/tests/bugs/core_0196_test.py +++ b/tests/bugs/core_0196_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-196 FBTEST: bugs.core_0190 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -25,7 +32,17 @@ substitutions = [('Statement failed, SQLSTATE = HY000', ''), ('record not found for user:.*', '')] -act = isql_act('db', test_script, substitutions=substitutions) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ Records affected: 0 From 75aff0dc40f8a1b71eaea9f63b82fc94f97db809 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 19:15:54 +0300 Subject: [PATCH 0604/1064] Added/Updated tests\bugs\core_0209_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0209_test.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_0209_test.py b/tests/bugs/core_0209_test.py index 8626eb61..8589b232 100644 --- a/tests/bugs/core_0209_test.py +++ b/tests/bugs/core_0209_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-209 FBTEST: bugs.core_0209 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -66,8 +73,24 @@ select * from test; """ -act = isql_act('db', test_script, - substitutions=[("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")]) +#act = isql_act('db', test_script, +# substitutions=[("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")]) + + +substitutions=[("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")] + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) + expected_stdout = """ insert into v_test values (11, 'a'); From 563732b77e9f63bbec339926e8e317367bfc7a6c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 19:16:45 +0300 Subject: [PATCH 0605/1064] Added/Updated tests\bugs\core_0209_test.py: minor change: remove old code --- tests/bugs/core_0209_test.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/bugs/core_0209_test.py b/tests/bugs/core_0209_test.py index 8589b232..b4846731 100644 --- a/tests/bugs/core_0209_test.py +++ b/tests/bugs/core_0209_test.py @@ -73,10 +73,6 @@ select * from test; """ -#act = isql_act('db', test_script, -# substitutions=[("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")]) - - substitutions=[("-At trigger 'V_TEST_BIU' line.*", "-At trigger 'V_TEST_BIU' line")] # QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings From 4cf8407c02f11f10292cb3a5b6db62ae31d6ff34 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 19:18:06 +0300 Subject: [PATCH 0606/1064] Added/Updated tests\bugs\core_0223_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0223_test.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0223_test.py b/tests/bugs/core_0223_test.py index 703830cd..4795295a 100644 --- a/tests/bugs/core_0223_test.py +++ b/tests/bugs/core_0223_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-223 FBTEST: bugs.core_0223 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -37,7 +44,19 @@ commit; """ -act = isql_act('db', test_script) +substitutions = [] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [ ('line: \\d+, col: \\d++', '') ] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) + expected_stdout = """ X 50000000 From 2115749220f47f3c2b5cb17a49e030ee7b942312 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 19:28:03 +0300 Subject: [PATCH 0607/1064] Added/Updated tests\bugs\core_0282_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0282_test.py | 73 ++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_0282_test.py b/tests/bugs/core_0282_test.py index 57ad3ca4..609b4bb8 100644 --- a/tests/bugs/core_0282_test.py +++ b/tests/bugs/core_0282_test.py @@ -7,41 +7,68 @@ DESCRIPTION: JIRA: CORE-282 FBTEST: bugs.core_0282 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t(a int); -create domain d int check(value > (select max(a) from t)); -commit;""" -db = db_factory(init=init_script) +db = db_factory() -test_script = """drop table t; -commit; -create table u(a d); -commit; -show table u; +test_script = """ + set list on; + create table test(f01 int); + create domain dm_int int check(value > (select max(f01) from test)); + commit; + drop table test; + commit; + create table test2(f01 dm_int); + commit; + show table test2; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """A (D) INTEGER Nullable - check(value > (select max(a) from t)) +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST.F01 + -there are 1 dependencies + F01 (DM_INT) INTEGER Nullable + check(value > (select max(f01) from test)) """ -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --COLUMN T.A --there are 1 dependencies + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST.F01 + -there are 1 dependencies + Table: TEST2 + F01 (DM_INT) INTEGER Nullable + check(value > (select max(f01) from test)) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f617eb5dc0023437b03ba61ccc51ecf43a20ae65 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 22 Jun 2025 19:33:50 +0300 Subject: [PATCH 0608/1064] Added/Updated tests\bugs\core_0480_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0480_test.py | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_0480_test.py b/tests/bugs/core_0480_test.py index cf1402f1..c4f5e670 100644 --- a/tests/bugs/core_0480_test.py +++ b/tests/bugs/core_0480_test.py @@ -7,32 +7,48 @@ DESCRIPTION: JIRA: CORE-480 FBTEST: bugs.core_0480 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table T1 (PK1 INTEGER, COL VARCHAR(10)); -commit;""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ + create table t1 (pk1 integer, col varchar(10)); + create table t2 (pk2 integer, fk1 varchar(10), col varchar(10), + foreign key (fk1) references t1 (pk1)); +""" -test_script = """create table T2 (PK2 INTEGER, FK1 VARCHAR(10), COL VARCHAR(10), -foreign key (FK1) references T1 (PK1)); +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -""" +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --CREATE TABLE T2 failed --could not find UNIQUE or PRIMARY KEY constraint in table T1 with specified columns +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE TABLE T2 failed + -could not find UNIQUE or PRIMARY KEY constraint in table T1 with specified columns """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4e2294bf12bde50d61eb405f93a4dd9f27bc5437 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 12:28:04 +0300 Subject: [PATCH 0609/1064] Added/Updated tests\bugs\core_0501_test.py: Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0501_test.py | 1254 ++++++++++++++-------------------- 1 file changed, 525 insertions(+), 729 deletions(-) diff --git a/tests/bugs/core_0501_test.py b/tests/bugs/core_0501_test.py index 9b670a23..f57c5d84 100644 --- a/tests/bugs/core_0501_test.py +++ b/tests/bugs/core_0501_test.py @@ -5,13 +5,25 @@ ISSUE: 852 TITLE: Optimization problem with COALESCE DESCRIPTION: - It tests many problems Adriano found when fixing CORE-501, CORE-1343 and CORE-2041. + Verify fixes for many issues Adriano found for CORE-501, CORE-1343 and CORE-2041. NOTES: -[25.04.2020] Fixed lot of bugs related to wrong count of updatable columns (they were not specified in DML). - Replaced test_type to 'ISQL' because all can be done wo Python calls. Checked on 3.0.6.33289, 4.0.0.1935. -[18.11.2020] Changed expected_stderr for parametrized statement "select coalesce(1 + cast(? ...), 2 + cast(? ...)) ...": - now it must be "-No SQLDA for input values provided" (was: "-Wrong number of parameters (expected 3, got 0)"). - Output became proper since CORE-6447 was fixed. + [25.04.2020] pzotov + Fixed lot of bugs related to wrong count of updatable columns (they were not specified in DML). + Replaced test_type to 'ISQL' because all can be done w/o Python calls. + Checked on 3.0.6.33289, 4.0.0.1935. + + [18.11.2020] pzotov + Changed expected_stderr for parametrized statement "select coalesce(1 + cast(? ...), 2 + cast(? ...)) ...": + now it must be "-No SQLDA for input values provided" (was: "-Wrong number of parameters (expected 3, got 0)"). + Output became proper since CORE-6447 was fixed. + + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + Also, for this test 'schema:' in SQLDA output is suppressed because as not relevant to check. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. JIRA: CORE-501 FBTEST: bugs.core_0501 """ @@ -19,8 +31,6 @@ import pytest from firebird.qa import * -substitutions = [('[ \t]+', ' ')] - db = db_factory() test_script = """ @@ -352,732 +362,518 @@ """ -act_1 = isql_act('db', test_script, substitutions=substitutions) - -expected_stdout = """ -MSG point-01 -N 1 -X 100 -CN 1 -CX 100 - -MSG point-01 -N 2 -X 20 -CN 2 -CX 20 - -MSG point-01 -N 3 -X 30 -CN 3 -CX 30 - - - -MSG point-02 -N 1 -X 100 -CN 1 -CX 100 - -MSG point-02 -N 2 -X 200 -CN 2 -CX 200 - -MSG point-02 -N 3 -X 30 -CN 3 -CX 30 - - - -MSG point-03 -N 1 -X 100 -CN 1 -CX 100 -VCN 1 - -MSG point-03 -N 2 -X 200 -CN 2 -CX 200 -VCN 2 - -MSG point-03 -N 3 -X 30 -CN 3 -CX 30 -VCN 3 - - - -MSG point-04 -N 1 -X 100 -CN 1 -CX 100 -VCN 1 - -MSG point-04 -N 2 -X 200 -CN 2 -CX 200 -VCN 2 - -MSG point-04 -N 3 -X 30 -CN 3 -CX 30 -VCN 3 - -MSG point-04 -N 4 -X 40 -CN 4 -CX 40 -VCN 4 - - - -MSG point-05 -N 1 -X 100 -CN 1 -CX 100 - -MSG point-05 -N 2 -X 200 -CN 2 -CX 200 - -MSG point-05 -N 3 -X 300 -CN 3 -CX 300 - -MSG point-05 -N 4 -X 40 -CN 4 -CX 40 - - - -MSG point-06 -N 1 -X 100 -CN 1 -CX 100 -VCN 1 - -MSG point-06 -N 2 -X 200 -CN 2 -CX 200 -VCN 2 - -MSG point-06 -N 3 -X 300 -CN 3 -CX 300 -VCN 3 - -MSG point-06 -N 4 -X 40 -CN 4 -CX 40 -VCN 4 - -MSG point-06 -N 1008 -X 88 -CN 1008 -CX 88 -VCN 1008 - - - -MSG point-07 -COAL_01 1 - -MSG point-07 -COAL_01 2 - -MSG point-07 -COAL_01 3 - -MSG point-07 -COAL_01 4 - -MSG point-07 -COAL_01 1008 - - - -MSG point-08 -COAL_02 1 - -MSG point-08 -COAL_02 2 - -MSG point-08 -COAL_02 3 - -MSG point-08 -COAL_02 4 - -MSG point-08 -COAL_02 1008 - - - -MSG point-09 -COAL_03 1 - -MSG point-09 -COAL_03 2 - -MSG point-09 -COAL_03 3 - -MSG point-09 -COAL_03 4 - -MSG point-09 -COAL_03 1008 - - - -MSG point-10 -COAL_04 1 - -MSG point-10 -COAL_04 2 - -MSG point-10 -COAL_04 3 - -MSG point-10 -COAL_04 4 - -MSG point-10 -COAL_04 1008 - - - -MSG point-11 -COAL_05 1 - -MSG point-11 -COAL_05 2 - -MSG point-11 -COAL_05 3 - -MSG point-11 -COAL_05 4 - - - -MSG point-12 -COAL_06 10 - -MSG point-12 -COAL_06 20 - -MSG point-12 -COAL_06 30 - -MSG point-12 -COAL_06 40 - -MSG point-12 -COAL_06 10080 - - - -MSG point-13 -COAL_07A 30 -COAL_07B 3000 - -MSG point-13 -COAL_07A 20 -COAL_07B 2000 - -MSG point-13 -COAL_07A 10 -COAL_07B 1000 - -MSG point-13 -COAL_07A 10080 -COAL_07B 880 - -MSG point-13 -COAL_07A 40 -COAL_07B 400 - +# NB: 'schema:' presents in the SQLDA output for FB 6.x, we can suppress it for *this* test: +substitutions = [('[ \t]+', ' '), ('table: schema: owner:', 'table: owner:')] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -MSG point-14 -COAL_08A 10080 -COAL_08B 880 +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -MSG point-14 -COAL_08A 40 -COAL_08B 400 +act = isql_act('db', test_script, substitutions=substitutions) -MSG point-14 -COAL_08A 30 -COAL_08B 3000 - -MSG point-14 -COAL_08A 20 -COAL_08B 2000 - -MSG point-14 -COAL_08A 10 -COAL_08B 1000 - - - -MSG point-15 -CASE_GROUP_BY_01 1 - -MSG point-15 -CASE_GROUP_BY_01 2 - -MSG point-15 -CASE_GROUP_BY_01 3 - -MSG point-15 -CASE_GROUP_BY_01 4 - -MSG point-15 -CASE_GROUP_BY_01 1008 - - - -MSG point-16 -CASE_GROUP_BY_02 1 - -MSG point-16 -CASE_GROUP_BY_02 2 - -MSG point-16 -CASE_GROUP_BY_02 3 - -MSG point-16 -CASE_GROUP_BY_02 4 - -MSG point-16 -CASE_GROUP_BY_02 1008 - - - -MSG point-17 -CASE_GROUP_BY_03 1 - -MSG point-17 -CASE_GROUP_BY_03 2 - -MSG point-17 -CASE_GROUP_BY_03 3 - -MSG point-17 -CASE_GROUP_BY_03 4 - - - -MSG point-18 -CASE_GROUP_BY_04 1008 - -MSG point-18 -CASE_GROUP_BY_04 4 - -MSG point-18 -CASE_GROUP_BY_04 3 - -MSG point-18 -CASE_GROUP_BY_04 2 - -MSG point-18 -CASE_GROUP_BY_04 1 - - - -MSG point-22 -N 1 - -MSG point-22 -N 2 - -MSG point-22 -N 3 - -MSG point-22 -N 4 - -MSG point-22 -N 1008 - - - -MSG point-23 -V2_N 1 -V2_X1 2 -V2_X2 3 - -MSG point-23 -V2_N 2 -V2_X1 3 -V2_X2 4 - -MSG point-23 -V2_N 3 -V2_X1 4 -V2_X2 5 - -MSG point-23 -V2_N 4 -V2_X1 5 -V2_X2 6 - -MSG point-23 -V2_N 1008 -V2_X1 1009 -V2_X2 1010 - - - -MSG point-24 -V3_N 1 -V3_X1 14 -V3_X2 26 - -MSG point-24 -V3_N 2 -V3_X1 16 -V3_X2 28 - -MSG point-24 -V3_N 3 -V3_X1 18 -V3_X2 30 - -MSG point-24 -V3_N 4 -V3_X1 20 -V3_X2 32 - -MSG point-24 -V3_N 1008 -V3_X1 2028 -V3_X2 2040 - - - -MSG point-25 -V4_N 1 -V4_X1 1 -V4_X2 3 - -MSG point-25 -V4_N 2 -V4_X1 1 -V4_X2 3 - -MSG point-25 -V4_N 3 -V4_X1 1 -V4_X2 3 - -MSG point-25 -V4_N 4 -V4_X1 1 -V4_X2 3 - -MSG point-25 -V4_N 1008 -V4_X1 1 -V4_X2 3 - - - -MSG point-26 -N 1 -X1 14 -X2 26 - -MSG point-26 -N 2 -X1 16 -X2 28 - -MSG point-26 -N 3 -X1 18 -X2 30 - -MSG point-26 -N 4 -X1 20 -X2 32 - -MSG point-26 -N 1008 -X1 2028 -X2 2040 - -MSG point-26 -N 1 -X1 14 -X2 26 - -MSG point-26 -N 2 -X1 16 -X2 28 - -MSG point-26 -N 3 -X1 18 -X2 30 - -MSG point-26 -N 4 -X1 20 -X2 32 - -MSG point-26 -N 1008 -X1 2028 -X2 2040 - - - -MSG point-27 -N 1 -X 100 -CN 1 -CX 100 - -MSG point-27 -N 2 -X 200 -CN 2 -CX 200 - -MSG point-27 -N 3 -X 300 -CN 3 -CX 300 - -MSG point-27 -N 4 -X 40 -CN 4 -CX 40 - -MSG point-27 -N 1008 -X 88 -CN 1008 -CX 88 - -MSG point-27 -N 5 -X 5 -CN 5 -CX 5 - - - -MSG point-28 -N 1 -X 100 -CN 1 -CX 100 -DC1 -DC2 - -MSG point-28 -N 2 -X 200 -CN 2 -CX 200 -DC1 -DC2 - -MSG point-28 -N 3 -X 300 -CN 3 -CX 300 -DC1 -DC2 - -MSG point-28 -N 4 -X 40 -CN 4 -CX 40 -DC1 -DC2 - -MSG point-28 -N 1008 -X 88 -CN 1008 -CX 88 -DC1 -DC2 - -MSG point-28 -N 5 -X 5 -CN 5 -CX 5 -DC1 -DC2 - -MSG point-28 -N 6 -X -CN 6 -CX -DC1 6 -DC2 - -MSG point-28 -N 7 -X -CN 7 -CX -DC1 -DC2 7 - - - -MSG point-29 -BC -1 - - - -INPUT message field count: 3 -01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: alias: - : table: owner: -02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: alias: - : table: owner: -03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: alias: - : table: owner: - -OUTPUT message field count: 2 -01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 8 charset: 0 NONE - : name: CONSTANT alias: MSG - : table: owner: -02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: COALESCE alias: COALESCE - : table: owner: -""" - -expected_stderr_1 = """ -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) -Statement failed, SQLSTATE = 23000 -Operation violates CHECK constraint T1_N on view or table T1 --At trigger 'CHECK_1' -Statement failed, SQLSTATE = 23000 -Operation violates CHECK constraint T1_CX on view or table T1 --At trigger 'CHECK_3' -Statement failed, SQLSTATE = 23000 -validation error for column "T1"."DC1", value "10" -Statement failed, SQLSTATE = 23000 -validation error for column "T1"."DC2", value "10" -Statement failed, SQLSTATE = 22012 -arithmetic exception, numeric overflow, or string truncation --Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. -Statement failed, SQLSTATE = 07002 -Dynamic SQL Error --SQLDA error --Wrong number of parameters (expected 3, got 0) -""" - -@pytest.mark.version('>=3.0,<3.0.8') -def test_1(act_1: Action): - act_1.expected_stdout = expected_stdout - act_1.expected_stderr = expected_stderr_1 - act_1.execute() - assert (act_1.clean_stderr == act_1.clean_expected_stderr and - act_1.clean_stdout == act_1.clean_expected_stdout) - -act_2 = isql_act('db', test_script, substitutions=substitutions) - -expected_stderr_2 = """ -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) -Statement failed, SQLSTATE = 23000 -Operation violates CHECK constraint T1_N on view or table T1 --At trigger 'CHECK_1' -Statement failed, SQLSTATE = 23000 -Operation violates CHECK constraint T1_CX on view or table T1 --At trigger 'CHECK_3' -Statement failed, SQLSTATE = 23000 -validation error for column "T1"."DC1", value "10" -Statement failed, SQLSTATE = 23000 -validation error for column "T1"."DC2", value "10" -Statement failed, SQLSTATE = 22012 -arithmetic exception, numeric overflow, or string truncation --Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. -Statement failed, SQLSTATE = 07002 -Dynamic SQL Error --SQLDA error --No SQLDA for input values provided +expected_stdout = """ + MSG point-01 + N 1 + X 100 + CN 1 + CX 100 + MSG point-01 + N 2 + X 20 + CN 2 + CX 20 + MSG point-01 + N 3 + X 30 + CN 3 + CX 30 + MSG point-02 + N 1 + X 100 + CN 1 + CX 100 + MSG point-02 + N 2 + X 200 + CN 2 + CX 200 + MSG point-02 + N 3 + X 30 + CN 3 + CX 30 + MSG point-03 + N 1 + X 100 + CN 1 + CX 100 + VCN 1 + MSG point-03 + N 2 + X 200 + CN 2 + CX 200 + VCN 2 + MSG point-03 + N 3 + X 30 + CN 3 + CX 30 + VCN 3 + MSG point-04 + N 1 + X 100 + CN 1 + CX 100 + VCN 1 + MSG point-04 + N 2 + X 200 + CN 2 + CX 200 + VCN 2 + MSG point-04 + N 3 + X 30 + CN 3 + CX 30 + VCN 3 + MSG point-04 + N 4 + X 40 + CN 4 + CX 40 + VCN 4 + MSG point-05 + N 1 + X 100 + CN 1 + CX 100 + MSG point-05 + N 2 + X 200 + CN 2 + CX 200 + MSG point-05 + N 3 + X 300 + CN 3 + CX 300 + MSG point-05 + N 4 + X 40 + CN 4 + CX 40 + MSG point-06 + N 1 + X 100 + CN 1 + CX 100 + VCN 1 + MSG point-06 + N 2 + X 200 + CN 2 + CX 200 + VCN 2 + MSG point-06 + N 3 + X 300 + CN 3 + CX 300 + VCN 3 + MSG point-06 + N 4 + X 40 + CN 4 + CX 40 + VCN 4 + MSG point-06 + N 1008 + X 88 + CN 1008 + CX 88 + VCN 1008 + MSG point-07 + COAL_01 1 + MSG point-07 + COAL_01 2 + MSG point-07 + COAL_01 3 + MSG point-07 + COAL_01 4 + MSG point-07 + COAL_01 1008 + MSG point-08 + COAL_02 1 + MSG point-08 + COAL_02 2 + MSG point-08 + COAL_02 3 + MSG point-08 + COAL_02 4 + MSG point-08 + COAL_02 1008 + MSG point-09 + COAL_03 1 + MSG point-09 + COAL_03 2 + MSG point-09 + COAL_03 3 + MSG point-09 + COAL_03 4 + MSG point-09 + COAL_03 1008 + MSG point-10 + COAL_04 1 + MSG point-10 + COAL_04 2 + MSG point-10 + COAL_04 3 + MSG point-10 + COAL_04 4 + MSG point-10 + COAL_04 1008 + MSG point-11 + COAL_05 1 + MSG point-11 + COAL_05 2 + MSG point-11 + COAL_05 3 + MSG point-11 + COAL_05 4 + MSG point-12 + COAL_06 10 + MSG point-12 + COAL_06 20 + MSG point-12 + COAL_06 30 + MSG point-12 + COAL_06 40 + MSG point-12 + COAL_06 10080 + MSG point-13 + COAL_07A 30 + COAL_07B 3000 + MSG point-13 + COAL_07A 20 + COAL_07B 2000 + MSG point-13 + COAL_07A 10 + COAL_07B 1000 + MSG point-13 + COAL_07A 10080 + COAL_07B 880 + MSG point-13 + COAL_07A 40 + COAL_07B 400 + MSG point-14 + COAL_08A 10080 + COAL_08B 880 + MSG point-14 + COAL_08A 40 + COAL_08B 400 + MSG point-14 + COAL_08A 30 + COAL_08B 3000 + MSG point-14 + COAL_08A 20 + COAL_08B 2000 + MSG point-14 + COAL_08A 10 + COAL_08B 1000 + MSG point-15 + CASE_GROUP_BY_01 1 + MSG point-15 + CASE_GROUP_BY_01 2 + MSG point-15 + CASE_GROUP_BY_01 3 + MSG point-15 + CASE_GROUP_BY_01 4 + MSG point-15 + CASE_GROUP_BY_01 1008 + MSG point-16 + CASE_GROUP_BY_02 1 + MSG point-16 + CASE_GROUP_BY_02 2 + MSG point-16 + CASE_GROUP_BY_02 3 + MSG point-16 + CASE_GROUP_BY_02 4 + MSG point-16 + CASE_GROUP_BY_02 1008 + MSG point-17 + CASE_GROUP_BY_03 1 + MSG point-17 + CASE_GROUP_BY_03 2 + MSG point-17 + CASE_GROUP_BY_03 3 + MSG point-17 + CASE_GROUP_BY_03 4 + MSG point-18 + CASE_GROUP_BY_04 1008 + MSG point-18 + CASE_GROUP_BY_04 4 + MSG point-18 + CASE_GROUP_BY_04 3 + MSG point-18 + CASE_GROUP_BY_04 2 + MSG point-18 + CASE_GROUP_BY_04 1 + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Invalid expression in the HAVING clause (neither an aggregate function nor a part of the GROUP BY clause) + MSG point-22 + N 1 + MSG point-22 + N 2 + MSG point-22 + N 3 + MSG point-22 + N 4 + MSG point-22 + N 1008 + MSG point-23 + V2_N 1 + V2_X1 2 + V2_X2 3 + MSG point-23 + V2_N 2 + V2_X1 3 + V2_X2 4 + MSG point-23 + V2_N 3 + V2_X1 4 + V2_X2 5 + MSG point-23 + V2_N 4 + V2_X1 5 + V2_X2 6 + MSG point-23 + V2_N 1008 + V2_X1 1009 + V2_X2 1010 + MSG point-24 + V3_N 1 + V3_X1 14 + V3_X2 26 + MSG point-24 + V3_N 2 + V3_X1 16 + V3_X2 28 + MSG point-24 + V3_N 3 + V3_X1 18 + V3_X2 30 + MSG point-24 + V3_N 4 + V3_X1 20 + V3_X2 32 + MSG point-24 + V3_N 1008 + V3_X1 2028 + V3_X2 2040 + MSG point-25 + V4_N 1 + V4_X1 1 + V4_X2 3 + MSG point-25 + V4_N 2 + V4_X1 1 + V4_X2 3 + MSG point-25 + V4_N 3 + V4_X1 1 + V4_X2 3 + MSG point-25 + V4_N 4 + V4_X1 1 + V4_X2 3 + MSG point-25 + V4_N 1008 + V4_X1 1 + V4_X2 3 + MSG point-26 + N 1 + X1 14 + X2 26 + MSG point-26 + N 2 + X1 16 + X2 28 + MSG point-26 + N 3 + X1 18 + X2 30 + MSG point-26 + N 4 + X1 20 + X2 32 + MSG point-26 + N 1008 + X1 2028 + X2 2040 + MSG point-26 + N 1 + X1 14 + X2 26 + MSG point-26 + N 2 + X1 16 + X2 28 + MSG point-26 + N 3 + X1 18 + X2 30 + MSG point-26 + N 4 + X1 20 + X2 32 + MSG point-26 + N 1008 + X1 2028 + X2 2040 + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint T1_N on view or table T1 + -At trigger CHECK_1 + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint T1_CX on view or table T1 + -At trigger CHECK_3 + MSG point-27 + N 1 + X 100 + CN 1 + CX 100 + MSG point-27 + N 2 + X 200 + CN 2 + CX 200 + MSG point-27 + N 3 + X 300 + CN 3 + CX 300 + MSG point-27 + N 4 + X 40 + CN 4 + CX 40 + MSG point-27 + N 1008 + X 88 + CN 1008 + CX 88 + MSG point-27 + N 5 + X 5 + CN 5 + CX 5 + Statement failed, SQLSTATE = 23000 + validation error for column T1.DC1, value 10 + Statement failed, SQLSTATE = 23000 + validation error for column T1.DC2, value 10 + MSG point-28 + N 1 + X 100 + CN 1 + CX 100 + DC1 + DC2 + MSG point-28 + N 2 + X 200 + CN 2 + CX 200 + DC1 + DC2 + MSG point-28 + N 3 + X 300 + CN 3 + CX 300 + DC1 + DC2 + MSG point-28 + N 4 + X 40 + CN 4 + CX 40 + DC1 + DC2 + MSG point-28 + N 1008 + X 88 + CN 1008 + CX 88 + DC1 + DC2 + MSG point-28 + N 5 + X 5 + CN 5 + CX 5 + DC1 + DC2 + MSG point-28 + N 6 + X + CN 6 + CX + DC1 6 + DC2 + MSG point-28 + N 7 + X + CN 7 + CX + DC1 + DC2 7 + MSG point-29 + BC -1 + Statement failed, SQLSTATE = 22012 + arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + INPUT message field count: 3 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: alias: + : table: schema: owner: + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: alias: + : table: schema: owner: + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: alias: + : table: schema: owner: + OUTPUT message field count: 2 + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 8 charset: 0 NONE + : name: CONSTANT alias: MSG + : table: schema: owner: + 02: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: COALESCE alias: COALESCE + : table: schema: owner: + Statement failed, SQLSTATE = 07002 + Dynamic SQL Error + -SQLDA error + -No SQLDA for input values provided """ -#-Wrong number of parameters (expected 3, got 0) @pytest.mark.version('>=3.0.8') -def test_2(act_2: Action): - act_2.expected_stdout = expected_stdout - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert (act_2.clean_stderr == act_2.clean_expected_stderr and - act_2.clean_stdout == act_2.clean_expected_stdout) +def test_2(act: Action): + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0e9ee70d049be846067c6da91257db070bed293b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 12:34:40 +0300 Subject: [PATCH 0610/1064] Added/Updated tests\bugs\core_0521_test.py: Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0521_test.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_0521_test.py b/tests/bugs/core_0521_test.py index 2ff73dd7..66a86377 100644 --- a/tests/bugs/core_0521_test.py +++ b/tests/bugs/core_0521_test.py @@ -7,6 +7,9 @@ DESCRIPTION: JIRA: CORE-521 FBTEST: bugs.core_0521 + [23.06.2025] pzotov + Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,22 +54,25 @@ commit; """ -act = isql_act('db', test_script, substitutions=[('execute', 'EXECUTE'), ('-Effective user is.*', '')]) +substitutions = [('[ \t]+', ' '), ('execute', 'EXECUTE'), ('-Effective user is.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - WHOAMI TMP$C0521 +expected_stdout_5x = """ + WHOAMI TMP$C0521 + Statement failed, SQLSTATE = 28000 + no permission for EXECUTE access to PROCEDURE PeRm """ -expected_stderr = """ +expected_stdout_6x = """ + WHOAMI TMP$C0521 Statement failed, SQLSTATE = 28000 - no permission for EXECUTE access to PROCEDURE PeRm + no permission for EXECUTE access to PROCEDURE "PUBLIC"."PeRm" """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout + From e3c6f24297a081f9f5d9fdb05ea8c1f3132d582b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 12:38:58 +0300 Subject: [PATCH 0611/1064] Added/Updated tests\bugs\core_0583_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0583_test.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_0583_test.py b/tests/bugs/core_0583_test.py index 46253533..ec85fec1 100644 --- a/tests/bugs/core_0583_test.py +++ b/tests/bugs/core_0583_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-583 FBTEST: bugs.core_0583 +NOTES: + [22.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -40,26 +47,31 @@ select * from test1; """ -act = isql_act('db', test_script, substitutions=[('-At trigger.*', '-At trigger')]) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('(-)?At trigger.*', 'At trigger')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) + expected_stdout = """ + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint TEST1_CHK on view or table TEST1 + At trigger Records affected: 0 Records affected: 0 Records affected: 0 Records affected: 0 """ -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - Operation violates CHECK constraint TEST1_CHK on view or table TEST1 - -At trigger 'CHECK_3' -""" - @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From b4c2f2a9dc07c1df6a8a250349fde708fa710e0d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 12:58:41 +0300 Subject: [PATCH 0612/1064] Added/Updated tests\bugs\core_0606_test.py: Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0606_test.py | 160 +++++++++++++++++------------------ 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/tests/bugs/core_0606_test.py b/tests/bugs/core_0606_test.py index 738366e7..87ca7af6 100644 --- a/tests/bugs/core_0606_test.py +++ b/tests/bugs/core_0606_test.py @@ -7,105 +7,105 @@ DESCRIPTION: JIRA: CORE-606 FBTEST: bugs.core_0606 +FBTEST: bugs.core_0521 + [23.06.2025] pzotov + Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). + Reimplemented: removed usage of hard-coded values for user and role name. Added substitutions to reduce irrelevant lines. + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('Statement failed, SQLSTATE = HY000', ''), - ('record not found for user:.*', ''), ('read/select', 'SELECT'), - ('Data source : Firebird::.*', 'Data source : Firebird::'), - ('-At block line: [\\d]+, col: [\\d]+', '-At block line'), - ('335545254 : Effective user is.*', '')] +substitutions = [ + ('[ \t]+', ' '), + ('.* Grant permissions .*', ''), + ('Statement failed, SQLSTATE = HY000', ''), + ('record not found for user:.*', ''), ('read/select', 'SELECT'), + ('Data source : Firebird::.*', 'Data source : Firebird::'), + ('(-)?At block line: [\\d]+, col: [\\d]+', ''), + ('335545254 : Effective user is.*', '') +] db = db_factory() for_cvc_role = role_factory('db', name='"FOR CVC"') for_role = role_factory('db', name='"FOR"') cvc_user = user_factory('db', name='cvc', password='pw') -test_script = """ - recreate table "t t"(data int); - commit; - insert into "t t" values(123456); - commit; - - grant "FOR CVC" to user cvc; - grant select on table "t t" to "FOR"; - commit; - - show grants; - commit; - - set list on; - set term ^; - execute block returns(who_am_i varchar(31), i_m_playing_role varchar(31)) as - begin - for - execute statement 'select current_user, current_role from rdb$database' - on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') - as user 'cvc' password 'pw' role '"FOR CVC"' - into who_am_i, i_m_playing_role - do - suspend; - end - ^ - - execute block returns(data int) as - begin - for - execute statement 'select data from "t t"' - on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') - as user 'cvc' password 'pw' role '"FOR CVC"' - into data - do - suspend; - end - ^ - set term ;^ - commit; - - -- |||||||||||||||||||||||||||| - -- ###################################||| FB 4.0+, SS and SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - delete from mon$attachments where mon$attachment_id != current_connection; - commit; -""" - -act = isql_act('db', test_script, substitutions=substitutions) +act = isql_act('db', substitutions = substitutions) -expected_stdout = """ -/* Grant permissions for this database */ -GRANT SELECT ON t t TO ROLE FOR -GRANT FOR CVC TO CVC - -WHO_AM_I CVC -I_M_PLAYING_ROLE FOR CVC -""" - -expected_stderr = """ +expected_stdout_5x = """ + GRANT SELECT ON t t TO ROLE FOR + GRANT FOR CVC TO CVC + WHO_AM_I CVC + I_M_PLAYING_ROLE FOR CVC Statement failed, SQLSTATE = 42000 Execute statement error at isc_dsql_prepare : 335544352 : no permission for SELECT access to TABLE t t Statement : select data from "t t" - Data source : Firebird::localhost:C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\E30.FDB - -At block line: 3, col: 7 + Data source : Firebird:: +""" +expected_stdout_6x = """ + GRANT SELECT ON PUBLIC."t t" TO ROLE "FOR" + GRANT "FOR CVC" TO CVC + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + WHO_AM_I CVC + I_M_PLAYING_ROLE FOR CVC + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544352 : no permission for SELECT access to TABLE "PUBLIC"."t t" + Statement : select data from "t t" + Data source : Firebird:: """ @pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action, cvc_user: User, for_role: Role, for_cvc_role: Role): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + test_sql = f""" + recreate table "t t"(data int); + commit; + insert into "t t" values(123456); + commit; + + grant {for_cvc_role.name} to user {cvc_user.name}; + grant select on table "t t" to {for_role.name}; + commit; + + show grants; + commit; + + set list on; + set term ^; + execute block returns(who_am_i varchar(31), i_m_playing_role varchar(31)) as + begin + for + execute statement 'select current_user, current_role from rdb$database' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user '{cvc_user.name}' password '{cvc_user.password}' role '{for_cvc_role.name}' + into who_am_i, i_m_playing_role + do + suspend; + end + ^ + + execute block returns(data int) as + begin + for + execute statement 'select data from "t t"' + on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME') + as user '{cvc_user.name}' password '{cvc_user.password}' role '{for_cvc_role.name}' + into data + do + suspend; + end + ^ + set term ;^ + commit; + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 9be44354d07e8812e64091a5bef7695fa8441289 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 13:09:21 +0300 Subject: [PATCH 0613/1064] Added/Updated tests\bugs\core_0625_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0625_test.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0625_test.py b/tests/bugs/core_0625_test.py index 89fef563..6628f75d 100644 --- a/tests/bugs/core_0625_test.py +++ b/tests/bugs/core_0625_test.py @@ -7,6 +7,13 @@ DESCRIPTION: Getting SQL error code = -104, Token unknown count. JIRA: CORE-625 FBTEST: bugs.core_0625 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -37,7 +44,17 @@ -- ^^ ^^ """ -act = isql_act('db', test_script, substitutions=[('\\(+', ''), ('\\)+', '')]) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('\\(+', ''), ('\\)+', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ PLAN SORT CUSTOMERS ORDER CUSTOMERS_COUNTRY From 2c04ed99ffb4ce3dfb5b923420a79f534a4b79ff Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:25:04 +0300 Subject: [PATCH 0614/1064] Added/Updated tests\bugs\core_0847_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0847_test.py | 81 ++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/tests/bugs/core_0847_test.py b/tests/bugs/core_0847_test.py index b6aaf3e6..fdd8b63d 100644 --- a/tests/bugs/core_0847_test.py +++ b/tests/bugs/core_0847_test.py @@ -7,76 +7,83 @@ DESCRIPTION: JIRA: CORE-847 FBTEST: bugs.core_0847 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +test_script = """ + set blob off; + set list on; + recreate table t ( - f1 varchar(10), - f2 varchar(10), - cf computed by (f1 || ' - ' || f2) + f1 smallint, + f2 smallint, + sum_f1_f2 computed by (f1+f2) ); - insert into t (f1,f2) values ('0123456789','abcdefghij'); + insert into t (f1,f2) values (1,2); commit; -""" -db = db_factory(init=init_script) - -test_script = """ - set blob off; - set list on; - - select f1,f2,cf as cf_before_altering from t; + select f1,f2,sum_f1_f2 as cf_before_altering from t; select b.rdb$field_name field_name, cast(a.rdb$computed_source as varchar(80)) computed_source_before_altering from rdb$fields a join rdb$relation_fields b on a.rdb$field_name = b.rdb$field_source - where b.rdb$field_name = upper('CF'); + where b.rdb$field_name = upper('SUM_F1_F2'); - alter table t alter cf type varchar(30); + alter table t alter sum_f1_f2 type bigint; commit; - select f1,f2,cf as cf_after_altering from t; + select f1,f2,sum_f1_f2 as cf_after_altering from t; select b.rdb$field_name field_name, cast(a.rdb$computed_source as varchar(80)) computed_source_after_altering from rdb$fields a join rdb$relation_fields b on a.rdb$field_name = b.rdb$field_source - where b.rdb$field_name = upper('CF'); + where b.rdb$field_name = upper('SUM_F1_F2'); """ -act = isql_act('db', test_script) +db = db_factory() -expected_stdout = """ - F1 0123456789 - F2 abcdefghij - CF_BEFORE_ALTERING 0123456789 - abcdefghij +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] - FIELD_NAME CF - COMPUTED_SOURCE_BEFORE_ALTERING (f1 || ' - ' || f2) +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) - F1 0123456789 - F2 abcdefghij - CF_AFTER_ALTERING 0123456789 - abcdefghij +act = isql_act('db', test_script, substitutions = substitutions) - FIELD_NAME CF - COMPUTED_SOURCE_AFTER_ALTERING (f1 || ' - ' || f2) -""" - -expected_stderr = """ +expected_stdout = """ + F1 1 + F2 2 + CF_BEFORE_ALTERING 3 + FIELD_NAME SUM_F1_F2 + COMPUTED_SOURCE_BEFORE_ALTERING (f1+f2) Statement failed, SQLSTATE = 42000 unsuccessful metadata update -ALTER TABLE T failed - -Cannot add or remove COMPUTED from column CF + -Cannot add or remove COMPUTED from column SUM_F1_F2 + F1 1 + F2 2 + CF_AFTER_ALTERING 3 + FIELD_NAME SUM_F1_F2 + COMPUTED_SOURCE_AFTER_ALTERING (f1+f2) """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 937f98f25ba54b165070b51c6607e3d5262daa31 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:43:25 +0300 Subject: [PATCH 0615/1064] Added/Updated tests\bugs\core_0850_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0850_test.py | 43 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_0850_test.py b/tests/bugs/core_0850_test.py index 84ebbd62..d473fcad 100644 --- a/tests/bugs/core_0850_test.py +++ b/tests/bugs/core_0850_test.py @@ -7,31 +7,46 @@ DESCRIPTION: JIRA: CORE-850 FBTEST: bugs.core_0850 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t2(a int, b int computed by (00)); -commit; +db = db_factory() + +test_script = """ + create table t2(a int, b int computed by (00)); + alter table t2 alter b set default 5; """ -db = db_factory(init=init_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -test_script = """alter table t2 alter b set default 5; -""" +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --ALTER TABLE T2 failed --Cannot add or remove COMPUTED from column B +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE T2 failed + -Cannot add or remove COMPUTED from column B """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0991def2aba748411e03be756eee152f7998dd57 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:46:46 +0300 Subject: [PATCH 0616/1064] Added/Updated tests\bugs\core_0851_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0851_test.py | 42 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_0851_test.py b/tests/bugs/core_0851_test.py index 9c196903..f4bccd12 100644 --- a/tests/bugs/core_0851_test.py +++ b/tests/bugs/core_0851_test.py @@ -7,31 +7,47 @@ DESCRIPTION: JIRA: CORE-851 FBTEST: bugs.core_0851 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (i integer); -commit; +db = db_factory() + +test_script = """ + create table t (f01 int); + create index ti on t(f01,f01); """ -db = db_factory(init=init_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -test_script = """create index ti on t(i,i); -""" +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --CREATE INDEX TI failed --Field I cannot be used twice in index TI +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE INDEX TI failed + -Field F01 cannot be used twice in index TI """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 36b6d59c308516107941aa79f1d1ffb3fa0a49a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:50:41 +0300 Subject: [PATCH 0617/1064] Added/Updated tests\bugs\core_0866_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0866_test.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_0866_test.py b/tests/bugs/core_0866_test.py index 03f7037c..1ce92249 100644 --- a/tests/bugs/core_0866_test.py +++ b/tests/bugs/core_0866_test.py @@ -12,18 +12,14 @@ import pytest from firebird.qa import * -init_script = """ + +test_script = """ recreate table test ( id integer not null, col varchar(20) not null ); insert into test (id, col) values (1, 'data'); commit; -""" - -db = db_factory(init=init_script) - -test_script = """ update rdb$relation_fields set rdb$null_flag = null where (rdb$field_name = upper('col')) and (rdb$relation_name = upper('test')); @@ -32,9 +28,21 @@ update test set col = null where id = 1; """ -act = isql_act('db', test_script) +db = db_factory() + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = 42000 UPDATE operation is not allowed for system table RDB$RELATION_FIELDS Statement failed, SQLSTATE = 23000 @@ -43,7 +51,7 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From cb46f6b06681064cf30deeb5a83c76fb2475bbe2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:51:29 +0300 Subject: [PATCH 0618/1064] Added/Updated tests\bugs\core_0866_test.py: added notes --- tests/bugs/core_0866_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/bugs/core_0866_test.py b/tests/bugs/core_0866_test.py index 1ce92249..fbf24355 100644 --- a/tests/bugs/core_0866_test.py +++ b/tests/bugs/core_0866_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-866 FBTEST: bugs.core_0866 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest From 0a47d1a77349cb4a90550c4940c6df97c456c387 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 15:58:38 +0300 Subject: [PATCH 0619/1064] Added/Updated tests\bugs\core_0878_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0878_test.py | 100 ++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/tests/bugs/core_0878_test.py b/tests/bugs/core_0878_test.py index c10ceafe..a12bf8af 100644 --- a/tests/bugs/core_0878_test.py +++ b/tests/bugs/core_0878_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-878 FBTEST: bugs.core_0878 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,50 +21,69 @@ db = db_factory() -test_script = """create table pk1 (i1 integer not null, i2 integer); -alter table pk1 add primary key (i1); -commit; -show table pk1; -alter table pk1 drop i1; -commit; +test_script = """ + create table pk1 (i1 integer not null, i2 integer); + alter table pk1 add primary key (i1); + commit; + show table pk1; + alter table pk1 drop i1; + commit; -create table pk2 (i1 integer not null, i2 integer); -alter table pk2 add constraint pk2_pk primary key (i1); -commit; -show table pk2; -alter table pk2 drop i1; -commit; + create table pk2 (i1 integer not null, i2 integer); + alter table pk2 add constraint pk2_pk primary key (i1); + commit; + show table pk2; + alter table pk2 drop i1; + commit; -create table pk3 (i1 integer not null primary key, i2 integer); -commit; -show table pk3; -alter table pk3 drop i1; -commit; + create table pk3 (i1 integer not null primary key, i2 integer); + commit; + show table pk3; + alter table pk3 drop i1; + commit; -show table pk1; + show table pk1; -show table pk2; + show table pk2; -show table pk3; + show table pk3; """ -act = isql_act('db', test_script) - -expected_stdout = """I1 INTEGER Not Null -I2 INTEGER Nullable -CONSTRAINT INTEG_2: - Primary key (I1) -I1 INTEGER Not Null -I2 INTEGER Nullable -CONSTRAINT PK2_PK: - Primary key (I1) -I1 INTEGER Not Null -I2 INTEGER Nullable -CONSTRAINT INTEG_5: - Primary key (I1) -I2 INTEGER Nullable -I2 INTEGER Nullable -I2 INTEGER Nullable + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('Table: .*', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) + + +expected_stdout = """ + I1 INTEGER Not Null + I2 INTEGER Nullable + CONSTRAINT INTEG_2: + Primary key (I1) + + I1 INTEGER Not Null + I2 INTEGER Nullable + CONSTRAINT PK2_PK: + Primary key (I1) + + I1 INTEGER Not Null + I2 INTEGER Nullable + CONSTRAINT INTEG_5: + Primary key (I1) + + I2 INTEGER Nullable + + I2 INTEGER Nullable + + I2 INTEGER Nullable """ @pytest.mark.version('>=3') From 64628735862aad1195409134e30ecdd2240943f0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 16:03:44 +0300 Subject: [PATCH 0620/1064] Added/Updated tests\bugs\core_0878_test.py: adjusted TITLE --- tests/bugs/core_0878_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_0878_test.py b/tests/bugs/core_0878_test.py index a12bf8af..934457be 100644 --- a/tests/bugs/core_0878_test.py +++ b/tests/bugs/core_0878_test.py @@ -3,7 +3,7 @@ """ ID: issue-1271 ISSUE: 1271 -TITLE: Problem when dropping column that is a primary key +TITLE: Column involved in the constraint (e.g. PK) could be dropped if constraint has user-defined name DESCRIPTION: JIRA: CORE-878 FBTEST: bugs.core_0878 From 78fbb68f8852e1f768831a915df22564cd4af62f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 16:11:10 +0300 Subject: [PATCH 0621/1064] Added/Updated tests\bugs\core_0878_test.py: adjusted TITLE --- tests/bugs/core_0878_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_0878_test.py b/tests/bugs/core_0878_test.py index 934457be..793ff7d5 100644 --- a/tests/bugs/core_0878_test.py +++ b/tests/bugs/core_0878_test.py @@ -2,8 +2,8 @@ """ ID: issue-1271 -ISSUE: 1271 -TITLE: Column involved in the constraint (e.g. PK) could be dropped if constraint has user-defined name +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1271 +TITLE: Column involved in the constraint (e.g. PK) could NOT be dropped if constraint has user-defined name DESCRIPTION: JIRA: CORE-878 FBTEST: bugs.core_0878 @@ -89,6 +89,6 @@ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 27ffb3382e143eb210a144295328350a578b26b4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 16:12:00 +0300 Subject: [PATCH 0622/1064] Added/Updated tests\bugs\core_0879_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0879_test.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_0879_test.py b/tests/bugs/core_0879_test.py index 3b460bc8..3491cbe3 100644 --- a/tests/bugs/core_0879_test.py +++ b/tests/bugs/core_0879_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-879 FBTEST: bugs.core_0879 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -23,9 +30,19 @@ show table tab; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('Table: .*', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -key size exceeds implementation restriction for index "IX" @@ -34,7 +51,7 @@ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1f46128aad1159dca8148ad461714249bdfbbbd8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 17:36:02 +0300 Subject: [PATCH 0623/1064] Added/Updated tests\bugs\core_0885_test.py: Reimplemented: removed usage of hard-coded values for user and role name. SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0885_test.py | 309 ++++++++++++++++++----------------- 1 file changed, 159 insertions(+), 150 deletions(-) diff --git a/tests/bugs/core_0885_test.py b/tests/bugs/core_0885_test.py index 2e0aaa98..e9ffc7af 100644 --- a/tests/bugs/core_0885_test.py +++ b/tests/bugs/core_0885_test.py @@ -7,169 +7,178 @@ DESCRIPTION: JIRA: CORE-885 FBTEST: bugs.core_0885 +NOTES: + [23.06.2025] pzotov + Reimplemented: removed usage of hard-coded values for user and role name. + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ +import locale import pytest from firebird.qa import * db = db_factory() -user_1_senior = user_factory('db', name='john_senior', password='sen') -user_1_junior = user_factory('db', name='mick_junior', password='jun') -role_1 = role_factory('db', name='modifier', do_not_create=True) - -test_script = """ - set wng off; - set list on; - - recreate table test(id int, text varchar(30), changed_by_user varchar(31), changed_by_role varchar(31)); - commit; - - set term ^; - create trigger test_biu for test active before insert or update position 0 as - begin - new.changed_by_user = current_user; - new.changed_by_role = current_role; - end - ^ - set term ;^ - commit; - - insert into test(id, text) values(1, 'Initial data, added by SYSDBA'); - insert into test(id, text) values(2, 'Initial data, added by SYSDBA'); - insert into test(id, text) values(3, 'Initial data, added by SYSDBA'); - select * from test; - commit; - - grant select on test to public; - grant create role to john_senior; - grant update(text) on test to john_senior with grant option; - commit; - - ---------------------------------------- - - --set echo on; - --show grants; - connect '$(DSN)' user 'JOHN_SENIOR' password 'sen'; - create role modifier; - commit; - grant update (text) on test to modifier; -- this CAN be done by john_senior because he was granted to control access on this field - grant modifier to mick_junior; -- this CAN be done by john_senior because he CREATED role 'modifier' and thus he is MEMBER of it. - commit; - --show grants; - - connect '$(DSN)' user 'MICK_JUNIOR' password 'jun' role 'MODIFIER'; - select current_user, current_role from rdb$database; - update test set text = 'Update-1: through the ROLE' where id = 1; - select * from test; - - commit; - - connect '$(DSN)' user 'JOHN_SENIOR' password 'sen'; - select current_user, current_role from rdb$database; - update test set text = 'Update-2: directly by USER' where id = 2; - select * from test; - commit; - - connect '$(DSN)' user 'JOHN_SENIOR' password 'sen'; - - -- ########################################################################################### - -- ### H e r e w e R E V O K E r i g h t t o u p d a t e c o l u m n ### - -- ########################################################################################### - -- ::: NB ::: See CORE-4836: - -- As of WI-T3.0.0.31873, if we want to revoke privilege on certain COLUMN update, we must do - -- it immediatelly after reconnect, NO issuing any DML here (like `select * from test` etc). - - revoke update(text) on test from modifier; ------------- ########### R E V O K E ######## - commit; - - connect '$(DSN)' user 'MICK_JUNIOR' password 'jun' role 'MODIFIER'; - select current_user, current_role from rdb$database; - update test set text = 'Update-3: again using ROLE' where id = 3; - select * from test; - - commit; - - connect '$(DSN)' user 'SYSDBA' password 'masterkey'; - - --drop role modifier; - drop table test; - commit; -""" -act = isql_act('db', test_script, substitutions=[('-Effective user is.*', '')]) +tmp_usr_senior = user_factory('db', name='tmp_0885_john_senior', password='sen') +tmp_usr_junior = user_factory('db', name='tmp_0885_mick_junior', password='jun') +tmp_role = role_factory('db', name='tmp_0885_modifier', do_not_create=True) -expected_stdout = """ - ID 1 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - ID 2 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - ID 3 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - - - USER MICK_JUNIOR - ROLE MODIFIER - ID 1 - TEXT Update-1: through the ROLE - CHANGED_BY_USER MICK_JUNIOR - CHANGED_BY_ROLE MODIFIER - ID 2 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - ID 3 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - - USER JOHN_SENIOR - ROLE NONE - ID 1 - TEXT Update-1: through the ROLE - CHANGED_BY_USER MICK_JUNIOR - CHANGED_BY_ROLE MODIFIER - ID 2 - TEXT Update-2: directly by USER - CHANGED_BY_USER JOHN_SENIOR - CHANGED_BY_ROLE NONE - ID 3 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE - - USER MICK_JUNIOR - ROLE MODIFIER - ID 1 - TEXT Update-1: through the ROLE - CHANGED_BY_USER MICK_JUNIOR - CHANGED_BY_ROLE MODIFIER - ID 2 - TEXT Update-2: directly by USER - CHANGED_BY_USER JOHN_SENIOR - CHANGED_BY_ROLE NONE - ID 3 - TEXT Initial data, added by SYSDBA - CHANGED_BY_USER SYSDBA - CHANGED_BY_ROLE NONE -""" +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' '), ('-Effective user is.*', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -expected_stderr = """ +act = isql_act('db', substitutions = substitutions) + +expected_stdout = """ + ID 1 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + ID 2 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + ID 3 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + USER TMP_0885_MICK_JUNIOR + ROLE TMP_0885_MODIFIER + ID 1 + TEXT Update-1: through the ROLE + CHANGED_BY_USER TMP_0885_MICK_JUNIOR + CHANGED_BY_ROLE TMP_0885_MODIFIER + ID 2 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + ID 3 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + USER TMP_0885_JOHN_SENIOR + ROLE NONE + ID 1 + TEXT Update-1: through the ROLE + CHANGED_BY_USER TMP_0885_MICK_JUNIOR + CHANGED_BY_ROLE TMP_0885_MODIFIER + ID 2 + TEXT Update-2: directly by USER + CHANGED_BY_USER TMP_0885_JOHN_SENIOR + CHANGED_BY_ROLE NONE + ID 3 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE + USER TMP_0885_MICK_JUNIOR + ROLE TMP_0885_MODIFIER Statement failed, SQLSTATE = 28000 no permission for UPDATE access to TABLE TEST + ID 1 + TEXT Update-1: through the ROLE + CHANGED_BY_USER TMP_0885_MICK_JUNIOR + CHANGED_BY_ROLE TMP_0885_MODIFIER + ID 2 + TEXT Update-2: directly by USER + CHANGED_BY_USER TMP_0885_JOHN_SENIOR + CHANGED_BY_ROLE NONE + ID 3 + TEXT Initial data, added by SYSDBA + CHANGED_BY_USER SYSDBA + CHANGED_BY_ROLE NONE """ - @pytest.mark.version('>=3.0') -def test_1(act: Action, user_1_senior: User, user_1_junior: User, role_1: Role): +def test_1(act: Action, tmp_usr_senior: User, tmp_usr_junior: User, tmp_role: Role): + + test_sql = f""" + set wng off; + set list on; + + recreate table test(id int, text varchar(30), changed_by_user varchar(31), changed_by_role varchar(31)); + commit; + + set term ^; + create trigger test_biu for test active before insert or update position 0 as + begin + new.changed_by_user = current_user; + new.changed_by_role = current_role; + end + ^ + set term ;^ + commit; + + insert into test(id, text) values(1, 'Initial data, added by SYSDBA'); + insert into test(id, text) values(2, 'Initial data, added by SYSDBA'); + insert into test(id, text) values(3, 'Initial data, added by SYSDBA'); + select * from test; + commit; + + grant select on test to public; + grant create role to {tmp_usr_senior.name}; + grant update(text) on test to {tmp_usr_senior.name} with grant option; + commit; + + ---------------------------------------- + + --set echo on; + connect '{act.db.dsn}' user '{tmp_usr_senior.name}' password '{tmp_usr_senior.password}'; + create role {tmp_role.name}; + commit; + grant update (text) on test to {tmp_role.name}; -- this CAN be done by john_senior because he was granted to control access on this field + grant {tmp_role.name} to {tmp_usr_junior.name}; -- this CAN be done by john_senior because he CREATED role 'modifier' and thus he is MEMBER of it. + commit; + + connect '{act.db.dsn}' user '{tmp_usr_junior.name}' password '{tmp_usr_junior.password}' role '{tmp_role.name}'; + select current_user, current_role from rdb$database; + update test set text = 'Update-1: through the ROLE' where id = 1; + select * from test; + + commit; + + connect '{act.db.dsn}' user '{tmp_usr_senior.name}' password '{tmp_usr_senior.password}'; + select current_user, current_role from rdb$database; + update test set text = 'Update-2: directly by USER' where id = 2; + select * from test; + commit; + + connect '{act.db.dsn}' user '{tmp_usr_senior.name}' password '{tmp_usr_senior.password}'; + + -- ########################################################################################### + -- ### H e r e w e R E V O K E r i g h t t o u p d a t e c o l u m n ### + -- ########################################################################################### + -- ::: NB ::: See CORE-4836: + -- As of WI-T3.0.0.31873, if we want to revoke privilege on certain COLUMN update, we must do + -- it immediatelly after reconnect, NO issuing any DML here (like `select * from test` etc). + + revoke update(text) on test from {tmp_role.name}; ------------- ########### R E V O K E ######## + commit; + + connect '{act.db.dsn}' user '{tmp_usr_junior.name}' password '{tmp_usr_junior.password}' role '{tmp_role.name}'; + select current_user, current_role from rdb$database; + update test set text = 'Update-3: again using ROLE' where id = 3; + select * from test; + + commit; + + connect '{act.db.dsn}' user 'SYSDBA' password 'masterkey'; + + --drop role {tmp_role.name}; + drop table test; + commit; + """ + act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.isql(switches = ['-q'], input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout From a191e5754b06826e54d7eff447e40d2223df378e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 17:51:03 +0300 Subject: [PATCH 0624/1064] Added/Updated tests\bugs\core_0886_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0886_test.py | 70 +++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/tests/bugs/core_0886_test.py b/tests/bugs/core_0886_test.py index c1d1db86..4d95fb3a 100644 --- a/tests/bugs/core_0886_test.py +++ b/tests/bugs/core_0886_test.py @@ -2,8 +2,8 @@ """ ID: issue-1279 -ISSUE: 1279 -TITLE: SPs in views +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1279 +TITLE: Ability to query a stored procedur from view. DESCRIPTION: JIRA: CORE-886 FBTEST: bugs.core_0886 @@ -12,45 +12,49 @@ import pytest from firebird.qa import * -init_script = """set term !!; -create procedure MY_PROCEDURE (input1 INTEGER) -returns (output1 INTEGER) -as begin - output1 = input1+1; - suspend; -end !! -set term ;!! -commit; - +db = db_factory() + +test_script = """ + set list on; + set blob all; + set term ^; + create procedure MY_PROCEDURE (input1 INTEGER) + returns (output1 INTEGER) as + begin + output1 = input1+1; + suspend; + end ^ + set term ;^ + commit; + + create view a_view as + select * from MY_PROCEDURE(1); + commit; + + select rdb$view_source as blob_id from rdb$relations where rdb$relation_name = upper('A_VIEW'); + select * from a_view; """ -db = db_factory(init=init_script) - -test_script = """create view a_view as -select * from MY_PROCEDURE(1); -commit; -show view a_view; -select *from a_view; -""" +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' '), ('BLOB_ID.*', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -expected_stdout = """Database: test.fdb, User: SYSDBA -SQL> CON> SQL> SQL> OUTPUT1 INTEGER Nullable -View Source: -==== ====== +act = isql_act('db', test_script, substitutions = substitutions) -select * from MY_PROCEDURE(1) -SQL> - OUTPUT1 -============ - 2 - -SQL> SQL>""" +expected_stdout = """ + select * from MY_PROCEDURE(1) + OUTPUT1 2 +""" @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 09edc51b7fc388d386547d138b8fd67b3ef573e4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 17:56:10 +0300 Subject: [PATCH 0625/1064] Added/Updated tests\bugs\core_0899_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0899_test.py | 228 ++++++++++++++++++----------------- 1 file changed, 118 insertions(+), 110 deletions(-) diff --git a/tests/bugs/core_0899_test.py b/tests/bugs/core_0899_test.py index ac45fa5c..c29ef25b 100644 --- a/tests/bugs/core_0899_test.py +++ b/tests/bugs/core_0899_test.py @@ -2,139 +2,147 @@ """ ID: issue-1296 -ISSUE: 1296 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1296 TITLE: Problems with explicit cursors in unwanted states DESCRIPTION: JIRA: CORE-899 FBTEST: bugs.core_0899 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table T (ID integer, TXT varchar(30)); -commit; - -insert into T values (1,'Text description'); -commit; - -set term ^; - -create procedure SP_OK returns (ID integer, TXT varchar(30)) -as - declare C cursor for ( select ID, TXT from T ); -begin - open C; - while (1 = 1) do - begin - fetch C into :ID, :TXT; - if (ROW_COUNT = 0) then - leave; - update T set TXT = 'OK' where current of C; - suspend; - end - close C; -end ^ - -create procedure SP_CLOSED returns (ID integer, TXT varchar(30)) -as - declare C cursor for ( select ID, TXT from T ); -begin - open C; - while (1 = 1) do - begin - fetch C into :ID, :TXT; - if (ROW_COUNT = 0) then - leave; - suspend; - end - close C; - update T set TXT = 'SP_CLOSED' where current of C; -end ^ - -create procedure SP_NOTOPEN returns (ID integer, TXT varchar(30)) -as - declare C cursor for ( select ID, TXT from T ); -begin - update T set TXT = 'SP_NOTOPEN' where current of C; - open C; - while (1 = 1) do - begin - fetch C into :ID, :TXT; - if (ROW_COUNT = 0) then - leave; - suspend; - end - close C; -end ^ - -create procedure SP_FETCHED returns (ID integer, TXT varchar(30)) -as - declare C cursor for ( select ID, TXT from T ); -begin - open C; - while (1 = 1) do - begin - fetch C into :ID, :TXT; - if (ROW_COUNT = 0) then - leave; - suspend; - end - update T set TXT = 'SP_FETCHED' where current of C; - close C; -end ^ - -set term ; ^ - -commit; +db = db_factory() + +test_script = """ + create table T (ID integer, TXT varchar(30)); + commit; + + insert into T values (1,'Text description'); + commit; + + set term ^; + + create procedure SP_OK returns (ID integer, TXT varchar(30)) + as + declare C cursor for ( select ID, TXT from T ); + begin + open C; + while (1 = 1) do + begin + fetch C into :ID, :TXT; + if (ROW_COUNT = 0) then + leave; + update T set TXT = 'OK' where current of C; + suspend; + end + close C; + end ^ + + create procedure SP_CLOSED returns (ID integer, TXT varchar(30)) + as + declare C cursor for ( select ID, TXT from T ); + begin + open C; + while (1 = 1) do + begin + fetch C into :ID, :TXT; + if (ROW_COUNT = 0) then + leave; + suspend; + end + close C; + update T set TXT = 'SP_CLOSED' where current of C; + end ^ + + create procedure SP_NOTOPEN returns (ID integer, TXT varchar(30)) + as + declare C cursor for ( select ID, TXT from T ); + begin + update T set TXT = 'SP_NOTOPEN' where current of C; + open C; + while (1 = 1) do + begin + fetch C into :ID, :TXT; + if (ROW_COUNT = 0) then + leave; + suspend; + end + close C; + end ^ + + create procedure SP_FETCHED returns (ID integer, TXT varchar(30)) + as + declare C cursor for ( select ID, TXT from T ); + begin + open C; + while (1 = 1) do + begin + fetch C into :ID, :TXT; + if (ROW_COUNT = 0) then + leave; + suspend; + end + update T set TXT = 'SP_FETCHED' where current of C; + close C; + end ^ + + set term ; ^ + + commit; + + set list on; + select * from SP_OK; + select * from SP_CLOSED; + select * from SP_NOTOPEN; + select * from SP_FETCHED; """ -db = db_factory(init=init_script) +substitutions=[('[ \t]+', ' '), ('line:\\s+\\d+,', 'line: x'), ('col:\\s+\\d+', 'col: y')] -test_script = """select * from SP_OK; -select * from SP_CLOSED; -select * from SP_NOTOPEN; -select * from SP_FETCHED; +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -""" +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -act = isql_act('db', test_script, - substitutions=[('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')]) +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - ID TXT -============ ============================== - 1 Text description + ID 1 + TXT Text description + ID 1 + TXT OK - ID TXT -============ ============================== - 1 OK + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + -At procedure SP_CLOSED line: x col: y - ID TXT -============ ============================== + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + -At procedure SP_NOTOPEN line: x col: y - ID TXT -============ ============================== - 1 OK -""" + ID 1 + TXT OK -expected_stderr = """Statement failed, SQLSTATE = 22000 -no current record for fetch operation --At procedure 'SP_CLOSED' line: 14, col: 3 -Statement failed, SQLSTATE = 22000 -no current record for fetch operation --At procedure 'SP_NOTOPEN' line: 5, col: 3 -Statement failed, SQLSTATE = 22000 -no current record for fetch operation --At procedure 'SP_FETCHED' line: 13, col: 3 + Statement failed, SQLSTATE = 22000 + no current record for fetch operation + -At procedure SP_FETCHED line: x col: y """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 99f7678fc42d2b293b8bbb7a2044ebe47425a987 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 17:56:39 +0300 Subject: [PATCH 0626/1064] Added/Updated tests\bugs\core_0886_test.py: added notes --- tests/bugs/core_0886_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/bugs/core_0886_test.py b/tests/bugs/core_0886_test.py index 4d95fb3a..0dd79008 100644 --- a/tests/bugs/core_0886_test.py +++ b/tests/bugs/core_0886_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-886 FBTEST: bugs.core_0886 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest From 9d154a80fab9b28320aefa3768a2811460ab2ad4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 20:50:30 +0300 Subject: [PATCH 0627/1064] Added/Updated tests\bugs\core_0907_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0907_test.py | 43 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_0907_test.py b/tests/bugs/core_0907_test.py index 0273390b..26a03d6e 100644 --- a/tests/bugs/core_0907_test.py +++ b/tests/bugs/core_0907_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-907 FBTEST: bugs.core_0907 + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -56,29 +62,38 @@ show table crash; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -expected_stdout = """ - A1 INTEGER Not Null - A2 INTEGER Not Null - A3 INTEGER Not Null - A4 INTEGER Not Null - A5 Computed by: (a2*a3*a4) -""" +substitutions = [('[ \t]+', ' '), ('Table: .*', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -expected_stderr = """ +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout = """ Statement failed, SQLSTATE = 22006 unsuccessful metadata update -Cannot make field A5 of table CRASH NOT NULL because there are NULLs present Statement failed, SQLSTATE = 23000 - validation error for column "CRASH"."A1", value "*** null ***" + validation error for column CRASH.A1, value *** null *** + + A1 INTEGER Not Null + A2 INTEGER Not Null + A3 INTEGER Not Null + A4 INTEGER Not Null + A5 Computed by: (a2*a3*a4) +""" + +expected_stderr = """ """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From bfdbd39fece0eb1424d6c21a73c88cb121b7b2dd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 20:53:22 +0300 Subject: [PATCH 0628/1064] Added/Updated tests\bugs\core_0908_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0908_test.py | 268 +++++++++++++++++++---------------- 1 file changed, 143 insertions(+), 125 deletions(-) diff --git a/tests/bugs/core_0908_test.py b/tests/bugs/core_0908_test.py index 2afff4a0..a56e4087 100644 --- a/tests/bugs/core_0908_test.py +++ b/tests/bugs/core_0908_test.py @@ -5,149 +5,167 @@ ISSUE: 1307 TITLE: Garbage in plan output of complex statement DESCRIPTION: - This is unfortunate case. The fix for 2.1 went through several "adjustments" and we've - get lost in changes. The result is that this was not properly fixed in 2.1 line (server - doesn't crash, but don't returns the truncated plan as supposed either). Now when 2.1 - line is at 2.1.3 we can hope for proper fix in 2.1.4. It should work as intended in 2.5 line. + This is unfortunate case. The fix for 2.1 went through several "adjustments" and we've + get lost in changes. The result is that this was not properly fixed in 2.1 line (server + doesn't crash, but don't returns the truncated plan as supposed either). Now when 2.1 + line is at 2.1.3 we can hope for proper fix in 2.1.4. It should work as intended in 2.5 line. JIRA: CORE-908 FBTEST: bugs.core_0908 +FBTEST: bugs.core_0907 + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """set term ^; - -create procedure big_plan - returns (x integer) -as -begin - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; - select 1 from rdb$database into :x; -/* select 1 from rdb$relations into :x; */ - suspend; -end ^ -set term ;^ +init_script = """ + set term ^; + create procedure big_plan + returns (x integer) + as + begin + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + select 1 from rdb$database into :x; + /* select 1 from rdb$relations into :x; */ + suspend; + end ^ + set term ;^ """ db = db_factory(init=init_script) -test_script = """set plan on; -select * from big_plan ; +test_script = """ + set plan on; + set list on; + select * from big_plan ; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """PLAN (BIG_PLAN NATURAL) -X -============ -1 +expected_stdout = """ + PLAN (BIG_PLAN NATURAL) + X 1 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From bd06c55bc1956e907a082d500866851fb4aa7b5a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 20:59:36 +0300 Subject: [PATCH 0629/1064] Added/Updated tests\bugs\core_0907_test.py: fixed dummy copy/paste: inserted forgotten 'NOTES:' section in proper place. --- tests/bugs/core_0907_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_0907_test.py b/tests/bugs/core_0907_test.py index 26a03d6e..a0005bbb 100644 --- a/tests/bugs/core_0907_test.py +++ b/tests/bugs/core_0907_test.py @@ -7,6 +7,7 @@ DESCRIPTION: JIRA: CORE-907 FBTEST: bugs.core_0907 +NOTES: [23.06.2025] pzotov ::: NB ::: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. From e1d1c1cecfb4ed0d42e78c45f53b1121697a19d2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 20:59:46 +0300 Subject: [PATCH 0630/1064] Added/Updated tests\bugs\core_0908_test.py: fixed dummy copy/paste: inserted forgotten 'NOTES:' section in proper place. --- tests/bugs/core_0908_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_0908_test.py b/tests/bugs/core_0908_test.py index a56e4087..8e58464d 100644 --- a/tests/bugs/core_0908_test.py +++ b/tests/bugs/core_0908_test.py @@ -11,7 +11,7 @@ line is at 2.1.3 we can hope for proper fix in 2.1.4. It should work as intended in 2.5 line. JIRA: CORE-908 FBTEST: bugs.core_0908 -FBTEST: bugs.core_0907 +NOTES: [23.06.2025] pzotov ::: NB ::: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. From e1c1b77bca612e5df3243bd2d7b2b698ed74b088 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 21:00:10 +0300 Subject: [PATCH 0631/1064] Added/Updated tests\bugs\core_0945_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0945_test.py | 49 ++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_0945_test.py b/tests/bugs/core_0945_test.py index d3c069e5..0aea17b3 100644 --- a/tests/bugs/core_0945_test.py +++ b/tests/bugs/core_0945_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-945 FBTEST: bugs.core_0945 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,28 +21,38 @@ db = db_factory() -test_script = """CREATE TABLE TAB_TestA ( - UID INTEGER NOT NULL PRIMARY KEY -); +test_script = """ + create table tmain ( + uid int not null primary key + ); + create table tdetl ( + uid int not null primary key, + pid integer constraint fk_tdetl references non_existing_0945(uid) on update cascade + ); +""" -CREATE TABLE TAB_TestB ( - UID INTEGER NOT NULL PRIMARY KEY, - TestA INTEGER CONSTRAINT FK_TestA REFERENCES TABTestA(UID) ON UPDATE CASCADE -); +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -""" +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --CREATE TABLE TAB_TESTB failed --Table TABTESTA not found +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE TABLE TDETL failed + -Table NON_EXISTING_0945 not found """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 49a5966198f04b1d3efd12b8f411fdfc99926f18 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 23 Jun 2025 21:01:36 +0300 Subject: [PATCH 0632/1064] Added/Updated tests\bugs\core_0995_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0995_test.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_0995_test.py b/tests/bugs/core_0995_test.py index 08284fa6..b2710660 100644 --- a/tests/bugs/core_0995_test.py +++ b/tests/bugs/core_0995_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-995 FBTEST: bugs.core_0995 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -69,7 +76,18 @@ order by orgaccount.id; """ -act = isql_act('db', test_script) + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ PLAN JOIN (ORGACCOUNT ORDER PK_ORGACCOUNT, ORG INDEX (PK_ORG)) @@ -79,6 +97,6 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 5f4480b6fb8b5428dbae030b9f4a449d860e272a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 09:05:25 +0300 Subject: [PATCH 0633/1064] Added/Updated tests\bugs\gh_5749_test.py: Fixed wrong value of charset that was used to connect: utf-8. This caused crash of isql in recent 6.x. --- tests/bugs/gh_5749_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_5749_test.py b/tests/bugs/gh_5749_test.py index 42c702aa..cc885992 100644 --- a/tests/bugs/gh_5749_test.py +++ b/tests/bugs/gh_5749_test.py @@ -27,6 +27,11 @@ -Token unknown - line 1, column 15 - Checked on 5.0.0.742 - all OK. + + [24.06.2025] pzotov + Fixed wrong value of charset that was used to connect: "utf-8". This caused crash of isql in recent 6.x. + https://github.com/FirebirdSQL/firebird/commit/5b41342b169e0d79d63b8d2fdbc033061323fa1b + Thanks to Vlad for solved problem. """ import pytest @@ -57,7 +62,6 @@ def test_1(act: Action, tmp_file: Path): tmp_file.write_bytes(whitespace_sql.encode('utf-8')) - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input_file=tmp_file, charset='utf-8', io_enc='utf-8', combine_output = True) + act.isql(switches=['-q'], input_file = tmp_file, charset = 'utf8', combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From f28ef91eae233e10076121b8bca04e0e1c775c91 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 09:09:19 +0300 Subject: [PATCH 0634/1064] Added/Updated tests\bugs\gh_7288_test.py: Fixed wrong value of charset that was used to connect: utf-8. This caused crash of isql in recent 6.x. --- tests/bugs/gh_7288_test.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_7288_test.py b/tests/bugs/gh_7288_test.py index 18a89dfd..d4546021 100644 --- a/tests/bugs/gh_7288_test.py +++ b/tests/bugs/gh_7288_test.py @@ -9,16 +9,23 @@ [20.02.2023] pzotov Confirmed crahses on 5.0.0.698 Checked on 5.0.0.733 -- all fine. + + [24.06.2025] pzotov + Fixed wrong value of charset that was used to connect: "utf-8". This caused crash of isql in recent 6.x. + https://github.com/FirebirdSQL/firebird/commit/5b41342b169e0d79d63b8d2fdbc033061323fa1b + Thanks to Vlad for solved problem. """ import pytest from firebird.qa import * from pathlib import Path db = db_factory(do_not_create=True, do_not_drop = True) -act = python_act('db') -db_tmp = temp_file('gh_7288.tmp.fdb') # db_factory(filename='tmp_core_7288.fdb', do_not_create=True, do_not_drop = True) -#tmp_file = temp_file('gh_7288.tmp.sql') +substitutions = [('[ \t]+', ' ')] + +act = python_act('db', substitutions = substitutions) + +db_tmp = temp_file('gh_7288.tmp.fdb') @pytest.mark.version('>=3.0.11') def test_1(act: Action, db_tmp: Path): @@ -39,6 +46,6 @@ def test_1(act: Action, db_tmp: Path): drop database; """ - expected_stdout = "COUNT 1" - act.isql(switches=['-q'], input = chk_sql, charset='utf-8', io_enc='utf-8', connect_db = False, credentials = False, combine_output = True) + expected_stdout = "COUNT 1" + act.isql(switches=['-q'], input = chk_sql, charset='utf8', io_enc='utf8', connect_db = False, credentials = False, combine_output = True) assert act.clean_stdout == expected_stdout From 7b799587d758935914a59fba56ae0d39a39ff17c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 09:42:39 +0300 Subject: [PATCH 0635/1064] Added/Updated tests\functional\gtcs\test_dsql_domain_22.py: see notes --- tests/functional/gtcs/test_dsql_domain_22.py | 98 +++++++++++++------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/tests/functional/gtcs/test_dsql_domain_22.py b/tests/functional/gtcs/test_dsql_domain_22.py index 3cd7cd77..8496467a 100644 --- a/tests/functional/gtcs/test_dsql_domain_22.py +++ b/tests/functional/gtcs/test_dsql_domain_22.py @@ -6,53 +6,78 @@ TITLE: Verify result of ALTER DOMAIN with changing NOT NULL flag and CHECK constraints when a table exists with field based on this domain DESCRIPTION: - Original test see in: - https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_22.script + Original test see in: + https://github.com/FirebirdSQL/fbtcs/blob/master/GTCS/tests/DSQL_DOMAIN_22.script - Comment in GTCS: - test for error conditions when using the alter domain statement on domains - that are already in use in table definitions, - with domain defaults and check constraints. + Comment in GTCS: + test for error conditions when using the alter domain statement on domains + that are already in use in table definitions, + with domain defaults and check constraints. - Test creates domain with DEFAULT value and CHECK constraint. - Initially domain definition: - 1) allows insertion of NULLs; - 2) have DEFAULT value which meets CHECK requirements. + Test creates domain with DEFAULT value and CHECK constraint. + Initially domain definition: + 1) allows insertion of NULLs; + 2) have DEFAULT value which meets CHECK requirements. - Then we create table and insert one record with DEFAULT value (it must pass) and second record with NULL. + Then we create table and insert one record with DEFAULT value (it must pass) and second record with NULL. - After this we try to change domain definition by adding NOT NULL clause - and it must - fail because of existing record with null. Finally, we replace CHECK constraint so that - its new expression will opposite to previous one, and try again to insert record with DEFAULT value. - It must fail because of new domain CHECK violation. + After this we try to change domain definition by adding NOT NULL clause - and it must + fail because of existing record with null. Finally, we replace CHECK constraint so that + its new expression will opposite to previous one, and try again to insert record with DEFAULT value. + It must fail because of new domain CHECK violation. - This is performed separately for each datatype (smallint, int, ...). + This is performed separately for each datatype (smallint, int, ...). - ::: NB-1 ::: - Test uses datatypes that did appear only in FB 4.0: INT128, DECFLOAT and - TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. - - ::: NB-2 ::: - Domain CHECK constraint *can* be changed so that existing data will not satisfy new expression. - Only NOT NULL is verified against data that were inserted in the table. + ::: NB-1 ::: + Test uses datatypes that did appear only in FB 4.0: INT128, DECFLOAT and + TIME[STAMP] WITH TIME ZONE. For this reason only FB 4.0+ can be tested. + ::: NB-2 ::: + Domain CHECK constraint *can* be changed so that existing data will not satisfy new expression. + Only NOT NULL is verified against data that were inserted in the table. NOTES: -[19.04.2022] pzotov - Manipulations with domain 'dom22_08' were changed: removed usage of EXP() to get value that is minimal - distinguish from zero (used before: exp(-745.NNNNN)). Reason: result is hardware-dependent (Intel vs AMD). + [19.04.2022] pzotov + Manipulations with domain 'dom22_08' were changed: removed usage of EXP() to get value that is minimal + distinguish from zero (used before: exp(-745.NNNNN)). Reason: result is hardware-dependent (Intel vs AMD). + + [23.06.2025] pzotov + Fixed wrong value of charset that was used to connect: "utf-8". This caused crash of isql in recent 6.x. + https://github.com/FirebirdSQL/firebird/commit/5b41342b169e0d79d63b8d2fdbc033061323fa1b + Thanks to Vlad for solved problem. + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * from pathlib import Path -substitutions = [('After line.*', ''), ('X_BLOB_20.*', ''), ('X_BLOB_21.*', ''), - ('X_BLOB_22.*', ''), ('DM_FVALID.*', ''), ('DM_FDEFAULT.*', ''), - ('0.0000000000000000', '0.000000000000000'), - ('X_DATE 20.*', 'X_DATE 20'), - ('validation error for column "TEST"."X_DATE", value .*', - 'validation error for column "TEST"."X_DATE"')] +substitutions = [ + ('After line.*', ''), + ('X_BLOB_20.*', ''), + ('X_BLOB_21.*', ''), + ('X_BLOB_22.*', ''), + ('DM_FVALID.*', ''), + ('DM_FDEFAULT.*', ''), + ('0.0000000000000000', '0.000000000000000'), + ('DATE_FROM_DOMAIN_DEFAULT .*', 'DATE_FROM_DOMAIN_DEFAULT'), + ('"TEST"."X_DATE", value .*', 'TEST.X_DATE'), + ] + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = python_act('db', substitutions = substitutions) db = db_factory() @@ -598,7 +623,7 @@ X_SML 0 X_INT 500 - X_DATE 2021-04-20 + DATE_FROM_DOMAIN_DEFAULT 2021-04-20 X_CHAR Wisła X_VCHR Norrström X_NUM -327.68 @@ -651,6 +676,8 @@ create domain dom22_01 as smallint default 0 check (value >= 0 and value < 100); create domain dom22_02 as integer default 500 check (value >= 500); + + -- NB: concrete value of date will be suppressed, see subst.: create domain dom22_03 as date default 'TODAY' check (value >= 'today'); -- CHECK-expression of this domain will be changed to @@ -754,7 +781,8 @@ recreate table test(x_date dom22_03); -- date default 'TODAY' check (value >= 'today'); - insert into test default values returning x_date; + -- must pass and issue current date, values will be suppressed, see 'susbtitutions': + insert into test default values returning x_date as DATE_FROM_DOMAIN_DEFAULT; insert into test values(null); commit; @@ -1079,7 +1107,7 @@ def test_1(act: Action, tmp_file: Path): act.expected_stdout = test_expected_stdout act.expected_stderr = test_expected_stderr - act.isql(switches=['-q'], input_file=tmp_file, charset='utf-8') + act.isql(switches=['-q'], input_file=tmp_file, charset='utf8') assert (act.clean_stdout == act.clean_expected_stdout and act.clean_stderr == act.clean_expected_stderr) From 81b184d381989b3fa9b9c72b826bb79a28dba189 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 10:17:54 +0300 Subject: [PATCH 0636/1064] Added/Updated tests\bugs\core_1029_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1029_test.py | 73 +++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/tests/bugs/core_1029_test.py b/tests/bugs/core_1029_test.py index 4f7c5b45..c4108f0e 100644 --- a/tests/bugs/core_1029_test.py +++ b/tests/bugs/core_1029_test.py @@ -2,61 +2,66 @@ """ ID: issue-1444 -ISSUE: 1444 -TITLE: ad plan in outer joins with IS NULL clauses (dependent on order of predicates) +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1444 +TITLE: Bad plan in outer joins with IS NULL clauses (dependent on order of predicates) DESCRIPTION: JIRA: CORE-1029 FBTEST: bugs.core_1029 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table tb1 (id int, col int) ; -create index tbi1 on tb1 (id) ; -create index tbi2 on tb1 (col) ; - -insert into tb1 values (1, 1) ; -insert into tb1 values (2, 2) ; -insert into tb1 values (1, null) ; - -commit; -""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ + create table tb1 (id int, col int) ; -test_script = """set plan on; + insert into tb1 values (1, 1) ; + insert into tb1 values (2, 2) ; + insert into tb1 values (1, null) ; + commit; + create index tbi1 on tb1 (id); + create index tbi2 on tb1 (col); + commit; -select * from tb1 a - left join tb1 b on a.id = b.id - where a.col is null and a.col+0 is null; + set planonly; + select * from tb1 a + left join tb1 b on a.id = b.id + where a.col is null and a.col+0 is null; -select * from tb1 a - left join tb1 b on a.id = b.id - where a.col+0 is null and a.col is null; + select * from tb1 a + left join tb1 b on a.id = b.id + where a.col+0 is null and a.col is null; """ -act = isql_act('db', test_script) - -expected_stdout = """PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) - ID COL ID COL -============ ============ ============ ============ - 1 1 1 - 1 1 +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) - ID COL ID COL -============ ============ ============ ============ - 1 1 1 - 1 1 +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ + PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) + PLAN JOIN (A INDEX (TBI2), B INDEX (TBI1)) """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From ac475fc74a17bf949c72b274b4549a979a9b509d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 10:21:50 +0300 Subject: [PATCH 0637/1064] Added/Updated tests\bugs\core_1056_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1056_test.py | 59 ++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_1056_test.py b/tests/bugs/core_1056_test.py index 03332c2f..b52ed597 100644 --- a/tests/bugs/core_1056_test.py +++ b/tests/bugs/core_1056_test.py @@ -7,50 +7,57 @@ DESCRIPTION: JIRA: CORE-1056 FBTEST: bugs.core_1056 + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (c varchar(10) character set win1250 collate pxw_csy); -insert into t values ('ch'); -commit; -""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ -test_script = """set plan on; + set list on; + create table t (c varchar(10) character set win1250 collate pxw_csy); + insert into t values ('ch'); + commit; -select * from t where c starting with 'c'; -commit; + set plan on; + select * from t where c starting with 'c'; + commit; -create index t_c on t (c); -commit; + create index t_c on t (c); + commit; -select * from t where c starting with 'c'; + select * from t where c starting with 'c'; """ -act = isql_act('db', test_script) - -expected_stdout = """ -PLAN (T NATURAL) - -C -========== -ch - +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -PLAN (T INDEX (T_C)) +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -C -========== -ch +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ + PLAN (T NATURAL) + C ch + PLAN (T INDEX (T_C)) + C ch """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 42ee232ec8f806eb51b3776dca3f4be6ef1d43e5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 11:26:31 +0300 Subject: [PATCH 0638/1064] Added/Updated tests\bugs\core_1083_test.py: Refactored: avoid usage of hard-coded user/role names. SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1083_test.py | 104 ++++++++++++++++------------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/tests/bugs/core_1083_test.py b/tests/bugs/core_1083_test.py index 27c33436..c105f277 100644 --- a/tests/bugs/core_1083_test.py +++ b/tests/bugs/core_1083_test.py @@ -2,78 +2,70 @@ """ ID: issue-1504 -ISSUE: 1504 -TITLE: User (not SYSDBA) what have privileges with grant option, can't revoke privileges, granted by other user or SYSDBA +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1504 +TITLE: User (not SYSDBA) that have privileges with grant option, can't revoke privileges, granted by other user or SYSDBA DESCRIPTION: JIRA: CORE-1083 FBTEST: bugs.core_1083 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('set echo .*', ''), - ('-TMP\\$C1083 is not grantor of (UPDATE|Update|update) on TAB2 to ROLE1.', - '-TMP$C1083 is not grantor of UPDATE on TAB2 to ROLE1.')] - db = db_factory() +tmp_user = user_factory('db', name='tmp$c1083', password='123') +tmp_role = role_factory('db', name='dba_helper') -test_script = """ - -- Refactored 05-JAN-2016: removed dependency on recource 'test_user'. - -- Checked on WI-V3.0.0.32266 (SS/SC/CS). - -- Checked 06.08.2018: added 'substitutions' because different case if some words in error message - -- ('Update' in 3.0.x vs 'UPDATE' in 4.0) - -- 3.0.4.33021: OK, 1.563s. - -- 4.0.0.1143: OK, 2.703s. +substitutions = [] - create or alter user tmp$c1083 password 'QweRtyUioP'; - commit; - recreate table tab1(col1 integer); - recreate table tab2(col2 integer); - commit; - create role role1; - grant update (col1) on tab1 to tmp$c1083 with grant option; - grant update (col2) on tab2 to role1; - commit; +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] - connect 'localhost:$(DATABASE_LOCATION)test.fdb' user 'TMP$C1083' password 'QweRtyUioP'; - --set bail on; - set echo on; - grant update(col1) on tab1 to role1; - revoke update(col1) on tab1 from role1; - revoke update(col2) on tab2 from role1; - set echo off; - commit; +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) - connect 'localhost:$(DATABASE_LOCATION)test.fdb' user 'SYSDBA' password 'masterkey'; - set echo on; - drop user tmp$c1083; - set echo off; - commit; - -- ('-TMP\\$C1083 is not grantor.*', '') -""" +act = isql_act('db', substitutions=substitutions) -act = isql_act('db', test_script, substitutions=substitutions) +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User, tmp_role: Role): -expected_stdout = """ - grant update(col1) on tab1 to role1; - revoke update(col1) on tab1 from role1; - revoke update(col2) on tab2 from role1; - drop user tmp$c1083; -""" + test_sql = f""" + recreate table tab1(col1 integer); + recreate table tab2(col2 integer); + commit; -expected_stderr = """ - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -REVOKE failed - -TMP$C1083 is not grantor of UPDATE on TAB2 to ROLE1. -""" + grant update (col1) on tab1 to {tmp_user.name} with grant option; + grant update (col2) on tab2 to {tmp_role.name}; + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + set echo on; + grant update(col1) on tab1 to {tmp_role.name}; + revoke update(col1) on tab1 from {tmp_role.name}; + revoke update(col2) on tab2 from {tmp_role.name}; + """ + + expected_stdout = f""" + grant update(col1) on tab1 to {tmp_role.name.upper()}; + revoke update(col1) on tab1 from {tmp_role.name.upper()}; + revoke update(col2) on tab2 from {tmp_role.name.upper()}; + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -REVOKE failed + -{tmp_user.name} is not grantor of UPDATE on TAB2 to {tmp_role.name.upper()}. + """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 17c2a4e9ac37aaf58246b0ce4a6b1c7d4b649dc4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 11:39:03 +0300 Subject: [PATCH 0639/1064] Added/Updated tests\bugs\core_1090_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1090_test.py | 55 +++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_1090_test.py b/tests/bugs/core_1090_test.py index fb302007..d7ddb44b 100644 --- a/tests/bugs/core_1090_test.py +++ b/tests/bugs/core_1090_test.py @@ -2,46 +2,55 @@ """ ID: issue-1511 -ISSUE: 1511 -TITLE: Error msg "Could not find UNIQUE INDEX" when in fact one is present +ISSUE: https://github.com/FirebirdSQL/firebird/issues/1511 +TITLE: FK-definition. Make error message more relevant when parent table has no appropriate PK/UK constraint. DESCRIPTION: JIRA: CORE-1090 FBTEST: bugs.core_1090 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Previous test title: Error msg "Could not find UNIQUE INDEX" when in fact one is present [CORE1090] + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (i integer not null); -create unique index ti on t(i); -commit; -""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ + create table tmain(id int not null); + create unique index tmain_id_unq on tmain(id); + create table tdetl(pid int references tmain(id)); +""" -test_script = """show table t; -show index ti; +substitutions = [] -create table t2 (i integer references t(i)); -""" +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -act = isql_act('db', test_script) +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -expected_stdout = """I INTEGER Not Null -TI UNIQUE INDEX ON T(I) -""" +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --CREATE TABLE T2 failed --could not find UNIQUE or PRIMARY KEY constraint in table T with specified columns +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE TABLE TDETL failed + -could not find UNIQUE or PRIMARY KEY constraint in table TMAIN with specified columns """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 139b23691e6a1757aa09943d18b893843c504bf5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 11:44:20 +0300 Subject: [PATCH 0640/1064] Added/Updated tests\bugs\core_1095_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. For this test 'schema:' in SQLDA output is suppressed because as not relevant to check. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1095_test.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_1095_test.py b/tests/bugs/core_1095_test.py index df5bc2b2..b89406a6 100644 --- a/tests/bugs/core_1095_test.py +++ b/tests/bugs/core_1095_test.py @@ -3,10 +3,18 @@ """ ID: issue-1517 ISSUE: 1517 -TITLE: Support BETWEEN predicate for select expressions +TITLE: Support `BETWEEN` predicate for select expressions DESCRIPTION: JIRA: CORE-1095 FBTEST: bugs.core_1095 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + Also, for this test 'schema:' in SQLDA output is suppressed because as not relevant to check. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -40,7 +48,19 @@ ; """ -act = isql_act('db', test_script) +# NB: 'schema:' presents in the SQLDA output for FB 6.x, we can suppress it for *this* test: +substitutions = [('[ \t]+', ' '), ('table: schema: owner:', 'table: owner:')] + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions=substitutions) expected_stdout = """ INPUT message field count: 2 From c410947f9647921402ba2d5c989d4600a2ccd9dd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 12:32:14 +0300 Subject: [PATCH 0641/1064] Added/Updated tests\bugs\core_5236_test.py: Adjusted explained plan in 6.x to actual. SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. For this test 'schema:' in SQLDA output is suppressed because as not relevant to check. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5236_test.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_5236_test.py b/tests/bugs/core_5236_test.py index f2d275d5..b04d5edc 100644 --- a/tests/bugs/core_5236_test.py +++ b/tests/bugs/core_5236_test.py @@ -24,16 +24,15 @@ JIRA: CORE-5236 FBTEST: bugs.core_5236 NOTES: - [16.06.2024] pzotov - Plan for FB 5.x and 6.x changed since 28-may-2024, build 6.0.0.363 #95442. - It was adjusted after talk with dimitr: must be the same for all FB versions - (with only difference: 'Sub-query' at the top line for FB 5.x+). - Changed filler character for show padding ('#' --> '.'). - - [23.03.2025] pzotov - Separated expected_out because plans differ on 6.x vs previous versions since commit fc12c0ef - ("Unnest IN/ANY/EXISTS subqueries and optimize them using semi-join algorithm (#8061)"). - Checked on 6.0.0.687-730aa8f; 5.0.3.1633-25a0817 + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + Also, for this test 'schema:' in SQLDA output is suppressed because as not relevant to check. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Adjusted explained plan in 6.x to actual. + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -70,7 +69,18 @@ db = db_factory(init=init_script) -act = python_act('db') +substitutions = [] + +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = python_act('db', substitutions=substitutions) #----------------------------------------------------------- From d6b2ff1711676901552188538e87facccdfbc128 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 12:42:07 +0300 Subject: [PATCH 0642/1064] Added/Updated tests\bugs\core_1130_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. For this test 'schema:' in SQLDA output is suppressed because as not relevant to check. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1130_test.py | 56 +++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/tests/bugs/core_1130_test.py b/tests/bugs/core_1130_test.py index b44f990b..a947e6bd 100644 --- a/tests/bugs/core_1130_test.py +++ b/tests/bugs/core_1130_test.py @@ -12,42 +12,44 @@ import pytest from firebird.qa import * -init_script = """SET TERM ^; -create procedure p - returns (r int) -as -begin - r = 1; - suspend; -end -^ -SET TERM ;^ -COMMIT; +db = db_factory() + +test_script = """ + set term ^; + create procedure sp_test returns (r int) as + begin + r = 1; + suspend; + end + ^ + set term ;^ + commit; + + set planonly; + select p.* + from sp_test p + left join (select rdb$relation_id from rdb$relations ) r on p.r = r.rdb$relation_id; """ -db = db_factory(init=init_script) +substitutions = [('RDB\\$INDEX_\\d+', 'RDB\\$INDEX')] -test_script = """SET PLAN ON; -select * -from p - left join ( select rdb$relation_id from rdb$relations ) r - on p.r = r.rdb$relation_id; +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -""" - -act = isql_act('db', test_script) +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -expected_stdout = """PLAN JOIN (P NATURAL, R RDB$RELATIONS INDEX (RDB$INDEX_1)) - - R RDB$RELATION_ID -============ =============== - 1 1 +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ + PLAN JOIN (P NATURAL, R RDB$RELATIONS INDEX (RDB$INDEX_1)) """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 85d86f32ce3e3f910f1baf910ffed718bd4e5f56 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 15:09:46 +0300 Subject: [PATCH 0643/1064] Added/Updated tests\bugs\core_1056_test.py: fixed wrong header: added missed 'NOTES:' --- tests/bugs/core_1056_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_1056_test.py b/tests/bugs/core_1056_test.py index b52ed597..064835d0 100644 --- a/tests/bugs/core_1056_test.py +++ b/tests/bugs/core_1056_test.py @@ -7,6 +7,7 @@ DESCRIPTION: JIRA: CORE-1056 FBTEST: bugs.core_1056 +NOTES: [24.06.2025] pzotov ::: NB ::: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. From af6882eba8a4ecf8cfd1afe6943b45241e20630f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 15:19:06 +0300 Subject: [PATCH 0644/1064] Added/Updated tests\bugs\core_0304_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0304_test.py | 670 +++++++++++++++-------------------- 1 file changed, 294 insertions(+), 376 deletions(-) diff --git a/tests/bugs/core_0304_test.py b/tests/bugs/core_0304_test.py index 719fa9ad..c77e2cf0 100644 --- a/tests/bugs/core_0304_test.py +++ b/tests/bugs/core_0304_test.py @@ -5,392 +5,310 @@ ISSUE: 637 TITLE: Any user can drop procedures, generators, exceptions DESCRIPTION: +JIRA: CORE-304 +FBTEST: bugs.core_0304 NOTES: -[24.01.2019] Added separate code for running on FB 4.0+. - UDF usage is deprecated in FB 4+, see: ".../doc/README.incompatibilities.3to4.txt". - Functions div, frac, dow, sdow, getExactTimestampUTC and isLeapYear got safe replacement - in UDR library "udf_compat", see it in folder: ../plugins/udr/ -[01.06.2021] Adjusted STDERR caused by fixes + [24.01.2019] Added separate code for running on FB 4.0+. + UDF usage is deprecated in FB 4+, see: ".../doc/README.incompatibilities.3to4.txt". + Functions div, frac, dow, sdow, getExactTimestampUTC and isLeapYear got safe replacement + in UDR library "udf_compat", see it in folder: ../plugins/udr/ + + [01.06.2021] Adjusted STDERR caused by fixes https://github.com/FirebirdSQL/firebird/pull/6833 https://github.com/FirebirdSQL/firebird/pull/6825 ("Correct error message for DROP VIEW") -JIRA: CORE-304 -FBTEST: bugs.core_0304 + + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Adjusted explained plan in 6.x to actual. + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -# version: 3.0 - db = db_factory() tmp_user = user_factory('db', name='tmp$c0304', password='123') -test_script_1 = """ - - DECLARE EXTERNAL FUNCTION strlen CSTRING(32767) RETURNS INTEGER BY VALUE ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf'; - - create domain dm_test int; - create collation name_coll for utf8 from unicode case insensitive; - create sequence g_test; - create exception e_test 'foo'; - create or alter procedure sp_test as begin end; - create table test(id int not null, x int); - alter table test add constraint test_pk primary key(id) using index test_pk; - create index test_x on test(x); - create view v_test as select * from test; - create role manager; - commit; - - set term ^; - create or alter trigger test_bi for test active - before insert position 0 - as - begin - new.id = coalesce(new.id, gen_id(g_test, 1) ); - end - ^ - set term ;^ - commit; - - connect '$(DSN)' user 'tmp$c0304' password '123'; - - -- All following statements should FAIL if current user is not SYSDBA: - - execute procedure sp_test; - - show sequence g_test; - - alter domain dm_test set default 123; - - alter domain dm_test set not null; - - alter domain dm_test drop not null; - - alter trigger test_bi inactive; - - - alter table test add z int; - - alter table test drop constraint test_pk; - - drop index test_x; - - drop view v_test; - - drop trigger test_bi; - - drop table test; - - drop role manager; - - drop procedure sp_test; - - drop sequence g_test; - - drop exception e_test; - - drop function strlen; - - - drop collation name_coll; - - rollback; -""" - -act_1 = isql_act('db', test_script_1) - - -expected_stderr_1 = """ - Statement failed, SQLSTATE = 28000 - no permission for EXECUTE access to PROCEDURE SP_TEST - - Statement failed, SQLSTATE = 28000 - no permission for USAGE access to GENERATOR G_TEST - There is no generator G_TEST in this database - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER DOMAIN DM_TEST failed - -no permission for ALTER access to DOMAIN DM_TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER DOMAIN DM_TEST failed - -no permission for ALTER access to DOMAIN DM_TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER DOMAIN DM_TEST failed - -no permission for ALTER access to DOMAIN DM_TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER TRIGGER TEST_BI failed - -no permission for ALTER access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER TABLE TEST failed - -no permission for ALTER access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -ALTER TABLE TEST failed - -no permission for ALTER access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP INDEX TEST_X failed - -no permission for ALTER access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP VIEW V_TEST failed - -no permission for DROP access to VIEW V_TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP TRIGGER TEST_BI failed - -no permission for ALTER access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP TABLE TEST failed - -no permission for DROP access to TABLE TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP ROLE MANAGER failed - -no permission for DROP access to ROLE MANAGER - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP PROCEDURE SP_TEST failed - -no permission for DROP access to PROCEDURE SP_TEST - - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP SEQUENCE G_TEST failed - -no permission for DROP access to GENERATOR G_TEST - - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP EXCEPTION E_TEST failed - -no permission for DROP access to EXCEPTION E_TEST - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP FUNCTION STRLEN failed - -no permission for DROP access to FUNCTION STRLEN - - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -DROP COLLATION NAME_COLL failed - -no permission for DROP access to COLLATION NAME_COLL - -""" - -@pytest.mark.version('>=3.0.8,<4.0') -def test_1(act_1: Action, tmp_user: User): - act_1.expected_stderr = expected_stderr_1 - act_1.execute() - assert act_1.clean_stderr == act_1.clean_expected_stderr - -# version: 4.0 - -test_script_2 = """ - -- See declaration sample in plugins\\udr\\UdfBackwardCompatibility.sql: - - create function UDR40_frac ( - val double precision - ) returns double precision - external name 'udf_compat!UC_frac' - engine udr; - - - create domain dm_test int; - create collation name_coll for utf8 from unicode case insensitive; - create sequence g_test; - create exception e_test 'foo'; - create or alter procedure sp_test as begin end; - create table test(id int not null, x int); - alter table test add constraint test_pk primary key(id) using index test_pk; - create index test_x on test(x); - create view v_test as select * from test; - create role manager; - commit; - - set term ^; - create or alter trigger test_bi for test active - before insert position 0 - as - begin - new.id = coalesce(new.id, gen_id(g_test, 1) ); - end - ^ - set term ;^ - commit; - - connect '$(DSN)' user 'tmp$c0304' password '123'; - - -- All following statements should FAIL if current user is not SYSDBA: - - execute procedure sp_test; - - show sequence g_test; - - alter domain dm_test set default 123; - - alter domain dm_test set not null; - - alter domain dm_test drop not null; - - alter trigger test_bi inactive; - - - alter table test add z int; - - alter table test drop constraint test_pk; - - drop index test_x; - - drop view v_test; - - drop trigger test_bi; - - drop table test; - - drop role manager; - - drop procedure sp_test; - - drop sequence g_test; - - drop exception e_test; - - drop function UDR40_frac; - - drop collation name_coll; - - rollback; -""" - -act_2 = isql_act('db', test_script_2) - -expected_stderr_2 = """ -Statement failed, SQLSTATE = 28000 -no permission for EXECUTE access to PROCEDURE SP_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -no permission for USAGE access to GENERATOR G_TEST --Effective user is TMP$C0304 - -There is no generator G_TEST in this database -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER DOMAIN DM_TEST failed --no permission for ALTER access to DOMAIN DM_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER DOMAIN DM_TEST failed --no permission for ALTER access to DOMAIN DM_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER DOMAIN DM_TEST failed --no permission for ALTER access to DOMAIN DM_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER TRIGGER TEST_BI failed --no permission for ALTER access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER TABLE TEST failed --no permission for ALTER access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --ALTER TABLE TEST failed --no permission for ALTER access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP INDEX TEST_X failed --no permission for ALTER access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP VIEW V_TEST failed --no permission for DROP access to VIEW V_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP TRIGGER TEST_BI failed --no permission for ALTER access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP TABLE TEST failed --no permission for DROP access to TABLE TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP ROLE MANAGER failed --no permission for DROP access to ROLE MANAGER --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP PROCEDURE SP_TEST failed --no permission for DROP access to PROCEDURE SP_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP SEQUENCE G_TEST failed --no permission for DROP access to GENERATOR G_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP EXCEPTION E_TEST failed --no permission for DROP access to EXCEPTION E_TEST --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP FUNCTION UDR40_FRAC failed --no permission for DROP access to FUNCTION UDR40_FRAC --Effective user is TMP$C0304 - -Statement failed, SQLSTATE = 28000 -unsuccessful metadata update --DROP COLLATION NAME_COLL failed --no permission for DROP access to COLLATION NAME_COLL --Effective user is TMP$C0304 - -""" - -@pytest.mark.version('>=4.0') -def test_2(act_2: Action, tmp_user: User): - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert act_2.clean_stderr == act_2.clean_expected_stderr +substitutions = [] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', substitutions = substitutions) + +@pytest.mark.version('>=3.0.8') +def test(act: Action, tmp_user: User): + if act.is_version('>=3.0.8,<4.0'): + special_ddl = """ + DECLARE EXTERNAL FUNCTION strlen CSTRING(32767) RETURNS INTEGER BY VALUE ENTRY_POINT 'IB_UDF_strlen' MODULE_NAME 'ib_udf'; + """ + else: + special_ddl = """ + create function strlen ( + val double precision + ) returns double precision + external name 'udf_compat!UC_frac' + engine udr; + """ + + test_sql = f""" + + {special_ddl} + + create domain dm_test int; + create collation name_coll for utf8 from unicode case insensitive; + create sequence g_test; + create exception e_test 'foo'; + create or alter procedure sp_test as begin end; + create table test(id int not null, x int); + alter table test add constraint test_pk primary key(id) using index test_pk; + create index test_x on test(x); + create view v_test as select * from test; + create role manager; + commit; + + set term ^; + create or alter trigger test_bi for test active + before insert position 0 + as + begin + new.id = coalesce(new.id, gen_id(g_test, 1) ); + end + ^ + set term ;^ + commit; + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + + -- All following statements should FAIL if current user is not SYSDBA: + + execute procedure sp_test; + show sequence g_test; + alter domain dm_test set default 123; + alter domain dm_test set not null; + alter domain dm_test drop not null; + alter trigger test_bi inactive; + alter table test add z int; + alter table test drop constraint test_pk; + drop index test_x; + drop view v_test; + drop trigger test_bi; + drop table test; + drop role manager; + drop procedure sp_test; + drop sequence g_test; + drop exception e_test; + drop function strlen; + drop collation name_coll; + rollback; + """ + + expected_stdout_3x = """ + Statement failed, SQLSTATE = 28000 + no permission for EXECUTE access to PROCEDURE SP_TEST + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G_TEST + There is no generator G_TEST in this database + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP INDEX TEST_X failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP VIEW V_TEST failed + -no permission for DROP access to VIEW V_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP TABLE TEST failed + -no permission for DROP access to TABLE TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP ROLE MANAGER failed + -no permission for DROP access to ROLE MANAGER + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP PROCEDURE SP_TEST failed + -no permission for DROP access to PROCEDURE SP_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP SEQUENCE G_TEST failed + -no permission for DROP access to GENERATOR G_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP EXCEPTION E_TEST failed + -no permission for DROP access to EXCEPTION E_TEST + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP FUNCTION STRLEN failed + -no permission for DROP access to FUNCTION STRLEN + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP COLLATION NAME_COLL failed + -no permission for DROP access to COLLATION NAME_COLL + """ + + expected_stdout_4x = f""" + Statement failed, SQLSTATE = 28000 + no permission for EXECUTE access to PROCEDURE SP_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G_TEST + -Effective user is {tmp_user.name.upper()} + There is no generator G_TEST in this database + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN DM_TEST failed + -no permission for ALTER access to DOMAIN DM_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -no permission for ALTER access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP INDEX TEST_X failed + -no permission for ALTER access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP VIEW V_TEST failed + -no permission for DROP access to VIEW V_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP TRIGGER TEST_BI failed + -no permission for ALTER access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP TABLE TEST failed + -no permission for DROP access to TABLE TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP ROLE MANAGER failed + -no permission for DROP access to ROLE MANAGER + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP PROCEDURE SP_TEST failed + -no permission for DROP access to PROCEDURE SP_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP SEQUENCE G_TEST failed + -no permission for DROP access to GENERATOR G_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP EXCEPTION E_TEST failed + -no permission for DROP access to EXCEPTION E_TEST + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP FUNCTION STRLEN failed + -no permission for DROP access to FUNCTION STRLEN + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP COLLATION NAME_COLL failed + -no permission for DROP access to COLLATION NAME_COLL + -Effective user is {tmp_user.name.upper()} + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_4x + act.isql(switches = ['-q'], input = test_sql, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 7c68d5f8882e2b2026c123450e64476e09334c64 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 15:49:39 +0300 Subject: [PATCH 0645/1064] Added/Updated tests\bugs\core_0800_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0800_test.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_0800_test.py b/tests/bugs/core_0800_test.py index ac1319a7..ec88fb60 100644 --- a/tests/bugs/core_0800_test.py +++ b/tests/bugs/core_0800_test.py @@ -7,6 +7,15 @@ DESCRIPTION: Domain DDL: move its CHECK clause from 'create' to 'alter' statement. JIRA: CORE-800 FBTEST: bugs.core_0800 +NOTES: + [24.06.2025] pzotov + FB-6.x snapshot must be 6.0.0.854-10b585b or newer, + see: #8622 (Regression: ISQL crashes on attempt to extract metadata when domain with reference to user-defined collation presents.) + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -43,7 +52,17 @@ db = db_factory(charset='UTF8', init=init_script) -act = python_act('db') +substitutions = [] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = python_act('db', substitutions = substitutions) expected_stdout = """ ALTER DOMAIN DM_TEST ADD CONSTRAINT From ce30152647128bf46358be754e83a6b15bf4339e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 16:26:58 +0300 Subject: [PATCH 0646/1064] Added/Updated tests\bugs\core_1145_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1145_test.py | 100 +++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/tests/bugs/core_1145_test.py b/tests/bugs/core_1145_test.py index f28d3e00..96790e94 100644 --- a/tests/bugs/core_1145_test.py +++ b/tests/bugs/core_1145_test.py @@ -7,77 +7,83 @@ DESCRIPTION: JIRA: CORE-1145 FBTEST: bugs.core_1145 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table expt1 (col1 int); -create table expt2 (col2 int); -commit; +db = db_factory() -insert into expt1 values (1); -insert into expt1 values (2); +test_script = """ + set list on; + create table expt1 (col1 int); + create table expt2 (col2 int); + commit; -insert into expt2 values (1); -insert into expt2 values (2); -commit; + insert into expt1 values (1); + insert into expt1 values (2); -create index iexpt1 on expt1 computed (col1 + 1); -create index iexpt2 on expt2 computed (col2 + 1); -commit; -""" + insert into expt2 values (1); + insert into expt2 values (2); + commit; -db = db_factory(init=init_script) + create index iexpt1 on expt1 computed (col1 + 1); + create index iexpt2 on expt2 computed (col2 + 1); + commit; -test_script = """set plan on; -select * from expt1 where col1 + 1 = 2; -select * from expt2 where col2 + 1 = 2; -commit; + set plan on; + select 'point-1' msg, e.* from expt1 e where col1 + 1 = 2; + select 'point-2' msg, e.* from expt2 e where col2 + 1 = 2; + commit; -drop index iexpt2; -commit; -- lockup + drop index iexpt2; + commit; -- lockup -select * from expt1 where col1 + 1 = 2; -select * from expt2 where col2 + 1 = 2; -commit; + select 'point-3' msg, e.* from expt1 e where col1 + 1 = 2; + select 'point-4' msg, e.* from expt2 e where col2 + 1 = 2; + commit; """ -act = isql_act('db', test_script) - -expected_stdout = """ -PLAN (EXPT1 INDEX (IEXPT1)) - - COL1 -============ - 1 +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -PLAN (EXPT2 INDEX (IEXPT2)) +substitutions = [('[ \t]+', ' ')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) - COL2 -============ - 1 - - -PLAN (EXPT1 INDEX (IEXPT1)) - - COL1 -============ - 1 +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ + PLAN (E INDEX (IEXPT1)) + MSG point-1 + COL1 1 -PLAN (EXPT2 NATURAL) + PLAN (E INDEX (IEXPT2)) + MSG point-2 + COL2 1 - COL2 -============ - 1 + PLAN (E INDEX (IEXPT1)) + MSG point-3 + COL1 1 + PLAN (E NATURAL) + MSG point-4 + COL2 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 6454760aad7413f5aa3f0dd7f93055c78656ab8e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 20:14:11 +0300 Subject: [PATCH 0647/1064] Added/Updated tests\bugs\core_1153_test.py: Separated execution plans for FB major versions prior/since 6.x. No substitutions are used to suppress schema name and quotes to enclosing object names. Checked on 6.0.0.858; 3.0.13.33813. --- tests/bugs/core_1153_test.py | 182 +++++++++++++++++++---------------- 1 file changed, 100 insertions(+), 82 deletions(-) diff --git a/tests/bugs/core_1153_test.py b/tests/bugs/core_1153_test.py index d7d1cd0c..6d41d43c 100644 --- a/tests/bugs/core_1153_test.py +++ b/tests/bugs/core_1153_test.py @@ -7,98 +7,116 @@ DESCRIPTION: JIRA: CORE-1153 FBTEST: bugs.core_1153 +NOTES: + [24.06.2025] pzotov + Separated execution plans for FB major versions prior/since 6.x. + No substitutions are used to suppress schema name and quotes to enclosing object names. + Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.858; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE D ( - ID VARCHAR(40) -); - - -CREATE TABLE M ( - ID VARCHAR(40) -); - - -INSERT INTO D (ID) VALUES ('AAA'); -INSERT INTO D (ID) VALUES ('aaa'); -INSERT INTO D (ID) VALUES ('Aaa Aaa'); -INSERT INTO D (ID) VALUES ('BBB'); -INSERT INTO D (ID) VALUES ('BBB'); -INSERT INTO D (ID) VALUES ('CCC'); - -COMMIT WORK; - -INSERT INTO M (ID) VALUES ('AAA Aaa'); -INSERT INTO M (ID) VALUES ('AAA Bbb'); -INSERT INTO M (ID) VALUES ('DDD Ddd'); -INSERT INTO M (ID) VALUES ('Bbb Aaa'); -INSERT INTO M (ID) VALUES ('Bbb Bbb'); - -COMMIT WORK; - -CREATE INDEX D_IDX1 ON D COMPUTED BY (upper(id)); -CREATE INDEX M_IDX1 ON M COMPUTED BY (UPPER(ID)); - -COMMIT WORK; +db = db_factory() + +test_script = """ + create table tdetl ( + sid varchar(40) + ); + create table tmain ( + sid varchar(40) + ); + + insert into tdetl(sid) values('AAA'); + insert into tdetl(sid) values('aaa'); + insert into tdetl(sid) values('Aaa Aaa'); + insert into tdetl(sid) values('BBB'); + insert into tdetl(sid) values('BBB'); + insert into tdetl(sid) values('CCC'); + commit; + + insert into tmain(sid) values ('AAA Aaa'); + insert into tmain(sid) values ('AAA Bbb'); + insert into tmain(sid) values ('DDD Ddd'); + insert into tmain(sid) values ('Bbb Aaa'); + insert into tmain(sid) values ('Bbb Bbb'); + commit; + + create index d_idx1 on tdetl computed by (upper(sid)); + create index m_idx1 on tmain computed by (upper(sid)); + commit; + + set list on; + set plan on; + alter index d_idx1 inactive; + + select distinct m.sid as m_sid, d.sid as d_did + from tmain m + left outer join tdetl d + on upper(m.sid) starting upper(d.sid) + order by m.sid; + + alter index d_idx1 active; + + select distinct m.sid as m_sid, d.sid as d_sid + from tmain m + left outer join tdetl d + on upper(m.sid) starting upper(d.sid) + order by m.sid; """ -db = db_factory(init=init_script) - -test_script = """SET PLAN ON; - -ALTER INDEX D_IDX1 INACTIVE; - -select distinct mm.ID as MID, dd.ID as DID -from m mm -left outer join d dd - on upper(mm.id) starting upper(dd.id) -order by mm.id ; - -ALTER INDEX D_IDX1 ACTIVE; - -select distinct mm.ID as MID, dd.ID as DID -from m mm -left outer join d dd - on upper(mm.id) starting upper(dd.id) -order by mm.id ; -""" - -act = isql_act('db', test_script) - -expected_stdout = """PLAN SORT (JOIN (MM NATURAL, DD NATURAL)) - -MID DID -======================================== ======================================== -AAA Aaa AAA -AAA Aaa Aaa Aaa -AAA Aaa aaa -AAA Bbb AAA -AAA Bbb aaa -Bbb Aaa BBB -Bbb Bbb BBB -DDD Ddd - -PLAN SORT (JOIN (MM NATURAL, DD NATURAL)) - -MID DID -======================================== ======================================== -AAA Aaa AAA -AAA Aaa Aaa Aaa -AAA Aaa aaa -AAA Bbb AAA -AAA Bbb aaa -Bbb Aaa BBB -Bbb Bbb BBB -DDD Ddd - -""" +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3') def test_1(act: Action): + + if act.is_version('<6'): + qry_plan = 'PLAN SORT (JOIN (M NATURAL, D NATURAL))' + else: + qry_plan = 'PLAN SORT (JOIN ("M" NATURAL, "D" NATURAL))' + + expected_stdout = f""" + {qry_plan} + M_SID AAA Aaa + D_DID AAA + M_SID AAA Aaa + D_DID Aaa Aaa + M_SID AAA Aaa + D_DID aaa + M_SID AAA Bbb + D_DID AAA + M_SID AAA Bbb + D_DID aaa + M_SID Bbb Aaa + D_DID BBB + M_SID Bbb Bbb + D_DID BBB + M_SID DDD Ddd + D_DID + + {qry_plan} + M_SID AAA Aaa + D_SID AAA + M_SID AAA Aaa + D_SID Aaa Aaa + M_SID AAA Aaa + D_SID aaa + M_SID AAA Bbb + D_SID AAA + M_SID AAA Bbb + D_SID aaa + M_SID Bbb Aaa + D_SID BBB + M_SID Bbb Bbb + D_SID BBB + M_SID DDD Ddd + D_SID + """ + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ec7a8fa474ee30f7a5d96eddc6dd2592f8367c9f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 22:25:50 +0300 Subject: [PATCH 0648/1064] Added/Updated tests\bugs\core_1162_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1162_test.py | 66 ++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/tests/bugs/core_1162_test.py b/tests/bugs/core_1162_test.py index eb7ff934..e9aa88e1 100644 --- a/tests/bugs/core_1162_test.py +++ b/tests/bugs/core_1162_test.py @@ -5,26 +5,15 @@ ISSUE: 1585 TITLE: Problem altering numeric field type DESCRIPTION: - create table tab (a numeric(4,2)); - insert into tab values (99.99); - select * from tab; - - A - ======= - 99.99 - - alter table tab alter a type numeric(4,3); - select * from tab; - - Statement failed, SQLCODE = -802 - arithmetic exception, numeric overflow, or string truncation - - BTW the database is not "corrupted" too badly - you can revert the change back by - alter table tab alter a type numeric(4,2); - and the engine is clever enough to convert data from stored format to requested one - directly, not through all intermediate format versions. JIRA: CORE-1162 FBTEST: bugs.core_1162 +NOTES: + [23.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,31 +21,36 @@ db = db_factory() -test_script = """create table tab ( a numeric(4,2) ); -insert into tab values (99.99); -alter table tab alter a type numeric(4,3); -select * from tab; +test_script = """ + create table tab ( a numeric(4,2) ); + insert into tab values (99.99); + alter table tab alter a type numeric(4,3); + set list on; + select * from tab; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -expected_stdout = """A -======= - 99.99 +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -""" +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --ALTER TABLE TAB failed --New scale specified for column A must be at most 2. +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TAB failed + -New scale specified for column A must be at most 2. + A 99.99 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1fb14b42ee6a773d90557c2a3c2180a1c81efc1f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 22:35:08 +0300 Subject: [PATCH 0649/1064] Added/Updated tests\bugs\core_1165_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1165_test.py | 92 ++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/tests/bugs/core_1165_test.py b/tests/bugs/core_1165_test.py index b0fb5821..f38150a4 100644 --- a/tests/bugs/core_1165_test.py +++ b/tests/bugs/core_1165_test.py @@ -7,59 +7,81 @@ DESCRIPTION: JIRA: CORE-1165 FBTEST: bugs.core_1165 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """recreate exception e1 'e1' ; -recreate exception e2 'e2' ; +db = db_factory() + +test_script = """ + set list on; + recreate exception exc_1 'exc_1' ; + recreate exception exc_2 'exc_2' ; + + set term ^; -set term ^; + create procedure sp_test as + begin + begin end + when exception exc_1, exception exc_2 do + begin + end + end + ^ + set term ;^ + commit; -create procedure p as -begin - begin end - when exception e1, exception e2 do - begin - end -end^ + select rd.rdb$depended_on_name depends_on_name + from rdb$dependencies rd + where upper(rd.rdb$dependent_name) = upper('sp_test') + order by depends_on_name + ; + commit; -set term ;^ + recreate exception exc_1 'exc_1'; + recreate exception exc_2 'exc_2'; """ -db = db_factory(init=init_script) +substitutions = [('[ \t]+', ' ')] +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] -test_script = """show depend p; +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) -recreate exception e1 'e1'; -recreate exception e2 'e2'; -""" +act = isql_act('db', test_script, substitutions = substitutions) -act = isql_act('db', test_script) +expected_stdout = """ + DEPENDS_ON_NAME EXC_1 + DEPENDS_ON_NAME EXC_2 -expected_stdout = """[P:Procedure] -E2:Exception, E1:Exception -+++ -""" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -EXCEPTION EXC_1 + -there are 1 dependencies -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --EXCEPTION E1 --there are 1 dependencies -Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --EXCEPTION E2 --there are 1 dependencies + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -EXCEPTION EXC_2 + -there are 1 dependencies """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 53d921c3858424448ab992906c1ed460ad891126 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:01:35 +0300 Subject: [PATCH 0650/1064] Added/Updated tests\bugs\core_1173_test.py: Separated execution plans for FB major versions prior/since 6.x. No substitutions are used to suppress schema name and quotes to enclosing object names. Checked on 6.0.0.858; 3.0.13.33813. --- tests/bugs/core_1173_test.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_1173_test.py b/tests/bugs/core_1173_test.py index bae6cb5f..305aba09 100644 --- a/tests/bugs/core_1173_test.py +++ b/tests/bugs/core_1173_test.py @@ -7,6 +7,13 @@ DESCRIPTION: Index based on COMPUTED-BY column must be taken in account by optimizer. JIRA: CORE-1173 FBTEST: bugs.core_1173 +NOTES: + [24.06.2025] pzotov + Separated execution plans for FB major versions prior/since 6.x. + No substitutions are used to suppress schema name and quotes to enclosing object names. + Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.858; 3.0.13.33813. """ import pytest @@ -77,16 +84,23 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST INDEX (TEST_ON_COMPUTED_FIELD_ASC)) PLAN (TEST INDEX (TEST_FDATE_FTIME_ASC)) PLAN (TEST INDEX (TEST_ON_COMPUTED_FIELD_DEC)) PLAN (TEST INDEX (TEST_FDATE_FTIME_DEC)) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_ON_COMPUTED_FIELD_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_FDATE_FTIME_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_ON_COMPUTED_FIELD_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_FDATE_FTIME_DEC")) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From a45386896ec35dd20b5480d159dc7bd387129e9e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:07:50 +0300 Subject: [PATCH 0651/1064] Added/Updated tests\bugs\core_1215_test.py: Separated execution plans for FB major versions prior/since 6.x. No substitutions are used to suppress schema name and quotes to enclosing object names. Checked on 6.0.0.858; 3.0.13.33813. --- tests/bugs/core_1215_test.py | 103 +++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/tests/bugs/core_1215_test.py b/tests/bugs/core_1215_test.py index ccbf7bfc..ffd60adf 100644 --- a/tests/bugs/core_1215_test.py +++ b/tests/bugs/core_1215_test.py @@ -7,73 +7,80 @@ DESCRIPTION: JIRA: CORE-1215 FBTEST: bugs.core_1215 +NOTES: + [24.06.2025] pzotov + Separated execution plans for FB major versions prior/since 6.x. + No substitutions are used to suppress schema name and quotes to enclosing object names. + Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.858; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE T (ID INT); -COMMIT; +init_script = """ + CREATE TABLE T (ID INT); + COMMIT; -set term ^; + set term ^; -EXECUTE BLOCK AS -DECLARE I INT = 0; -BEGIN - WHILE (I < 50000) DO - BEGIN - INSERT INTO T VALUES (1); - I = I + 1; - END -END^ + EXECUTE BLOCK AS + DECLARE I INT = 0; + BEGIN + WHILE (I < 50000) DO + BEGIN + INSERT INTO T VALUES (1); + I = I + 1; + END + END^ -set term ;^ -commit; + set term ;^ + commit; -CREATE INDEX IDX_T ON T (ID); -COMMIT; + CREATE INDEX IDX_T ON T (ID); + COMMIT; """ db = db_factory(init=init_script) -test_script = """set plan on; -SELECT COUNT(*) FROM T ; -SELECT COUNT(*) FROM T WHERE ID >= 1 ; -SELECT COUNT(*) FROM T WHERE ID = 1 ; -SELECT COUNT(*) FROM T WHERE ID <= 1 ; +test_script = """ + set list on; + set plan on; + SELECT COUNT(*) FROM T ; + SELECT COUNT(*) FROM T WHERE ID >= 1 ; + SELECT COUNT(*) FROM T WHERE ID = 1 ; + SELECT COUNT(*) FROM T WHERE ID <= 1 ; """ -act = isql_act('db', test_script) - -expected_stdout = """PLAN (T NATURAL) - - COUNT -===================== - 50000 - -PLAN (T INDEX (IDX_T)) - - COUNT -===================== - 50000 - -PLAN (T INDEX (IDX_T)) - - COUNT -===================== - 50000 - -PLAN (T INDEX (IDX_T)) - - COUNT -===================== - 50000 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + PLAN (T NATURAL) + COUNT 50000 + PLAN (T INDEX (IDX_T)) + COUNT 50000 + PLAN (T INDEX (IDX_T)) + COUNT 50000 + PLAN (T INDEX (IDX_T)) + COUNT 50000 +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" NATURAL) + COUNT 50000 + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."IDX_T")) + COUNT 50000 + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."IDX_T")) + COUNT 50000 + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."IDX_T")) + COUNT 50000 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 90343de5c12f5c96aff1cc6dbd529b867103ffc7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:30:50 +0300 Subject: [PATCH 0652/1064] Added/Updated tests\bugs\core_1291_test.py: Added substitutions in orde to suppress output of procedure header info. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1291_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_1291_test.py b/tests/bugs/core_1291_test.py index d0c5056e..3a9262af 100644 --- a/tests/bugs/core_1291_test.py +++ b/tests/bugs/core_1291_test.py @@ -3,10 +3,14 @@ """ ID: issue-1712 ISSUE: 1712 -TITLE: Can't transliterate character set when look at procedure text in database just created from script (and thus in ODS 11.1) +TITLE: Can't transliterate character set when look at procedure text in database just created from script DESCRIPTION: JIRA: CORE-1291 FBTEST: bugs.core_1291 +NOTES: + [24.06.2025] pzotov + Added substitutions in orde to suppress output of procedure header info. This data irrelevant to the test. + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -661,9 +665,10 @@ db = db_factory(do_not_create=True) -act = python_act('db') +substitutions = [ ('Procedure: \\S+.*', ''), ('Procedure text:', '') ] +act = python_act('db', substitutions = substitutions) -expected_stdout = """Procedure text: +expected_stdout = """ ============================================================================= DECLARE VARIABLE NDSDiv DOUBLE PRECISION; DECLARE VARIABLE ID_ExportFieldDoc Integer; From 2c93d0b875552e368eb53733e4a2f8f40e61e475 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:33:37 +0300 Subject: [PATCH 0653/1064] Added/Updated tests\bugs\core_1295_test.py: Separated execution plans for FB major versions prior/since 6.x. No substitutions are used to suppress schema name and quotes to enclosing object names. Checked on 6.0.0.858; 3.0.13.33813. --- tests/bugs/core_1295_test.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_1295_test.py b/tests/bugs/core_1295_test.py index 70e787be..6e411f94 100644 --- a/tests/bugs/core_1295_test.py +++ b/tests/bugs/core_1295_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-1295 FBTEST: bugs.core_1295 +NOTES: + [24.06.2025] pzotov + Separated execution plans for FB major versions prior/since 6.x. + No substitutions are used to suppress schema name and quotes to enclosing object names. + Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,19 +21,26 @@ db = db_factory() -test_script = """SET PLANONLY; -select * from rdb$relations where rdb$db_key = ? and rdb$relation_id = 0; -select * from rdb$relations where rdb$db_key = ? and rdb$relation_name = 'RDB$RELATIONS';""" +test_script = """ + SET PLANONLY; + select * from rdb$relations where rdb$db_key = ? and rdb$relation_id = 0; + select * from rdb$relations where rdb$db_key = ? and rdb$relation_name = 'RDB$RELATIONS'; +""" act = isql_act('db', test_script) -expected_stdout = """PLAN (RDB$RELATIONS INDEX ()) -PLAN (RDB$RELATIONS INDEX ()) +expected_stdout_5x = """ + PLAN (RDB$RELATIONS INDEX ()) + PLAN (RDB$RELATIONS INDEX ()) +""" + +expected_stdout_6x = """ + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ()) + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ()) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 4a87033edaa89d10fa19db80f63635363528398c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:39:59 +0300 Subject: [PATCH 0654/1064] Added/Updated tests\bugs\core_1306_test.py: Separated execution plans for FB major versions prior/since 6.x. No substitutions are used to suppress schema name and quotes to enclosing object names. Checked on 6.0.0.858; 3.0.13.33813. --- tests/bugs/core_1306_test.py | 60 +++++++++++++++++------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/tests/bugs/core_1306_test.py b/tests/bugs/core_1306_test.py index 70081183..7dd17cda 100644 --- a/tests/bugs/core_1306_test.py +++ b/tests/bugs/core_1306_test.py @@ -12,44 +12,42 @@ import pytest from firebird.qa import * -init_script = """CREATE TABLE "TABLE" (ID INTEGER NOT NULL PRIMARY KEY); - -COMMIT; - -INSERT INTO "TABLE" (ID) VALUES (1); -INSERT INTO "TABLE" (ID) VALUES (2); -INSERT INTO "TABLE" (ID) VALUES (3); - -COMMIT; - -CREATE VIEW "VIEW" AS SELECT * FROM "TABLE"; - -commit;""" - -db = db_factory(init=init_script) - -test_script = """set plan on; - -SELECT * FROM "TABLE" WHERE ID = 1 -UNION ALL -SELECT * FROM "VIEW" WHERE ID = 1 ; +db = db_factory() + +test_script = """ + set list on; + create table "TABLE" (id integer not null primary key); + commit; + insert into "TABLE" (id) values (1); + insert into "TABLE" (id) values (2); + insert into "TABLE" (id) values (3); + commit; + create view "VIEW" as select * from "TABLE"; + commit; + set plan on; + select * from "TABLE" where id = 1 + union all + select * from "VIEW" where id = 1 ; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ -PLAN (TABLE INDEX (RDB$PRIMARY1), VIEW TABLE INDEX (RDB$PRIMARY1)) - - ID -============ - 1 - 1 +expected_stdout_5x = """ + PLAN (TABLE INDEX (RDB$PRIMARY1), VIEW TABLE INDEX (RDB$PRIMARY1)) + ID 1 + ID 1 +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."TABLE" INDEX ("PUBLIC"."RDB$PRIMARY1"), "PUBLIC"."VIEW" "PUBLIC"."TABLE" INDEX ("PUBLIC"."RDB$PRIMARY1")) + ID 1 + ID 1 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 01413befca8fdf4c2987a261e31265d76eef6353 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:43:56 +0300 Subject: [PATCH 0655/1064] Added/Updated tests\bugs\core_1316_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1316_test.py | 56 +++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_1316_test.py b/tests/bugs/core_1316_test.py index 46eb8d44..443fb6c1 100644 --- a/tests/bugs/core_1316_test.py +++ b/tests/bugs/core_1316_test.py @@ -7,6 +7,15 @@ DESCRIPTION: JIRA: CORE-1316 FBTEST: bugs.core_1316 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Adjusted explained plan in 6.x to actual. + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,26 +23,39 @@ db = db_factory() -test_script = """create procedure get_something(id integer not null) as begin end; -commit; -execute procedure get_something(NULL); -execute procedure get_something(1); -set term ^; -create procedure p0(inp int) as declare i int not null; begin i = inp; end^ -set term ;^ -commit; -execute procedure p0(null); -execute procedure p0(1); +test_script = """ + create procedure get_something(id integer not null) as begin end; + commit; + execute procedure get_something(NULL); + execute procedure get_something(1); + set term ^; + create procedure sp_test(inp int) as declare i int not null; begin i = inp; end^ + set term ;^ + commit; + execute procedure sp_test(null); + execute procedure sp_test(1); """ -act = isql_act('db', test_script, substitutions=[('line: \\d+, col: \\d+', '')]) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [('line: \\d+, col: \\d+', '')] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stderr = """ + Statement failed, SQLSTATE = 42000 + validation error for variable ID, value "*** null ***" + -At procedure 'GET_SOMETHING' -expected_stderr = """Statement failed, SQLSTATE = 42000 -validation error for variable ID, value "*** null ***" --At procedure 'GET_SOMETHING' -Statement failed, SQLSTATE = 42000 -validation error for variable I, value "*** null ***" --At procedure 'P0' line: 1, col: 63 + Statement failed, SQLSTATE = 42000 + validation error for variable I, value "*** null ***" + -At procedure 'SP_TEST' line: 1, col: 63 """ @pytest.mark.version('>=3') From 3d325b57e0a2800d80fa794f44b9b81affaeaf65 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:53:06 +0300 Subject: [PATCH 0656/1064] Added/Updated tests\bugs\core_1384_test.py: Removed 'show collations' because this command irrelevant here. --- tests/bugs/core_1384_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/bugs/core_1384_test.py b/tests/bugs/core_1384_test.py index 9e278d4f..5a37ebe0 100644 --- a/tests/bugs/core_1384_test.py +++ b/tests/bugs/core_1384_test.py @@ -34,15 +34,12 @@ test_script = """ set list on; -show collation; select * from v_test; """ act = isql_act('db', test_script) expected_stdout = """ - COLL_ES, CHARACTER SET ISO8859_1, FROM EXTERNAL ('ES_ES_CI_AI'), 'SPECIALS-FIRST=1' - COLL_FR, CHARACTER SET ISO8859_1, FROM EXTERNAL ('FR_FR'), CASE INSENSITIVE, ACCENT INSENSITIVE, 'SPECIALS-FIRST=1' RESULT_FOR_ES_CI_AI 0 RESULT_FOR_FR_CI_AI 0 RESULT_FOR_ES_CI_AI 0 From 2af311266800388a737bf696106d57a67dce1efd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:55:54 +0300 Subject: [PATCH 0657/1064] Added/Updated tests\bugs\core_1386_test.py: Removed 'show table' because this command irrelevant. --- tests/bugs/core_1386_test.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_1386_test.py b/tests/bugs/core_1386_test.py index 67fd6f8b..def6f7ab 100644 --- a/tests/bugs/core_1386_test.py +++ b/tests/bugs/core_1386_test.py @@ -14,30 +14,27 @@ db = db_factory() -test_script = """CREATE TABLE TAB1 (COL1 INTEGER, COL2 GENERATED ALWAYS AS (COL1 +1), COL3 INTEGER GENERATED ALWAYS AS (COL1 +1)); -COMMIT; -SHOW TABLE TAB1; -INSERT INTO TAB1 (COL1) VALUES (1); -COMMIT; -SELECT * FROM TAB1; - +test_script = """ + set list on; + create table tab1 (col1 integer, col2 generated always as (col1 +1), col3 integer generated always as (col1 +1)); + commit; + insert into tab1 (col1) values (1); + commit; + select * from tab1; """ -act = isql_act('db', test_script) - -expected_stdout = """COL1 INTEGER Nullable -COL2 Computed by: (COL1 +1) -COL3 Computed by: (COL1 +1) - - COL1 COL2 COL3 -============ ===================== ============ - 1 2 2 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ + COL1 1 + COL2 2 + COL3 2 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From f3baab7128619f18a5850caf1ebac484b4aa56bd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 24 Jun 2025 23:59:05 +0300 Subject: [PATCH 0658/1064] Added/Updated tests\bugs\core_1395_test.py: SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1395_test.py | 48 +++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_1395_test.py b/tests/bugs/core_1395_test.py index 2b559250..d0ce6dd1 100644 --- a/tests/bugs/core_1395_test.py +++ b/tests/bugs/core_1395_test.py @@ -7,34 +7,54 @@ DESCRIPTION: JIRA: CORE-1395 FBTEST: bugs.core_1395 +NOTES: + [24.06.2025] pzotov + ::: NB ::: + SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. + See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md + + Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE TEST ( ID INTEGER ); -CREATE DOMAIN TEST_DOMAIN AS INTEGER CHECK (EXISTS(SELECT * FROM TEST WHERE ID=VALUE)); +init_script = """ + create table test ( id integer ); + create domain test_domain as integer + check ( exists(select * from test where id=value) ); """ db = db_factory(init=init_script) -test_script = """DROP TABLE TEST; -COMMIT; - +test_script = """ + drop table test; + commit; """ -act = isql_act('db', test_script) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] + +substitutions = [] +for p in addi_subst_tokens.split(' '): + substitutions.append( (p, '') ) + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --COLUMN TEST.ID --there are 1 dependencies +expected_stdout = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST.ID + -there are 1 dependencies """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 126848d1d34772ad866e95e22685a1c28482c6a9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 10:32:16 +0300 Subject: [PATCH 0659/1064] Added/Updated tests\bugs\core_1010_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 3.0.13.33813. See notes. --- tests/bugs/core_1010_test.py | 41 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_1010_test.py b/tests/bugs/core_1010_test.py index 0c7d02cb..968865eb 100644 --- a/tests/bugs/core_1010_test.py +++ b/tests/bugs/core_1010_test.py @@ -5,11 +5,23 @@ ISSUE: 1420 TITLE: Local buffer overrun in DYN_error() that takes down the server DESCRIPTION: - We have a local buffer overrun in DYN_error(), while copying tdbb_status_vector to - local_status. It seems to be the first time (DYN errors + stack trace facility) when 20 - status words are not enough to store the complete error info. + We have a local buffer overrun in DYN_error(), while copying tdbb_status_vector to + local_status. It seems to be the first time (DYN errors + stack trace facility) when 20 + status words are not enough to store the complete error info. JIRA: CORE-1010 FBTEST: bugs.core_1010 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Minimal snapshot number for 6.x: 6.0.0.863, see letter from Adriano, 24.06.2025 13:12, commit: + https://github.com/FirebirdSQL/firebird/commit/9c6855b516de4e4aea78e7df782e297f4e220287 + + Checked on 6.0.0.863; 3.0.13.33813. + +24.06.2025 DEFERRED, SENT Q TO ADRIANO + """ import pytest @@ -18,14 +30,13 @@ db = db_factory() test_script = """ - -- Removed old code: all attempts to create triggers on SYSTEM tables now are prohibited, even for SYSDBA. - create exception ex_test '!!!'; + + create exception ex_test 'Trigger suddenly was created!'; commit; set term ^ ; create or alter trigger rdb$procedures_biu for rdb$procedures - active after update or delete position 0 - as + active after update or delete position 0 as begin exception ex_test; end @@ -41,18 +52,24 @@ commit; """ -act = isql_act('db', test_script, substitutions=[('line:.*', ''), ('col:.*', '')]) +act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update -CREATE OR ALTER TRIGGER RDB$PROCEDURES_BIU failed -no permission for ALTER access to TABLE RDB$PROCEDURES """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 28000 + CREATE OR ALTER TRIGGER "SYSTEM"."RDB$PROCEDURES_BIU" failed + -Cannot CREATE/ALTER/DROP TRIGGER in SYSTEM schema +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 07204e32533b2e6235ee51756fc262f54c9b6e72 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 10:32:44 +0300 Subject: [PATCH 0660/1064] Added/Updated tests\bugs\core_1010_test.py: minor change: removed old comment --- tests/bugs/core_1010_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/bugs/core_1010_test.py b/tests/bugs/core_1010_test.py index 968865eb..ae5b5db1 100644 --- a/tests/bugs/core_1010_test.py +++ b/tests/bugs/core_1010_test.py @@ -19,9 +19,6 @@ https://github.com/FirebirdSQL/firebird/commit/9c6855b516de4e4aea78e7df782e297f4e220287 Checked on 6.0.0.863; 3.0.13.33813. - -24.06.2025 DEFERRED, SENT Q TO ADRIANO - """ import pytest From 8e54049b41707a53e4bfb401615ce076e2f54eb4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 11:28:18 +0300 Subject: [PATCH 0661/1064] Added/Updated tests\bugs\core_1058_test.py: Minimal snapshot number for 6.x: 6.0.0.863. See notes. --- tests/bugs/core_1058_test.py | 45 ++++++++---------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/tests/bugs/core_1058_test.py b/tests/bugs/core_1058_test.py index 4c7b2e05..7d011048 100644 --- a/tests/bugs/core_1058_test.py +++ b/tests/bugs/core_1058_test.py @@ -11,18 +11,16 @@ [05.10.2023] pzotov 1. Removed SHOW command for check result because its output often changes. It is enough for this test to verify just absense of any error messages. - 2. Changed test queries. - 3. ::: NB ::: Have a question about case when we change table fields type using - alter table test - alter column fld_domain_defined type varchar(10) character set win1250 - ,alter column fld_explicit_type1 type varchar(10) character set win1252 - ,alter column fld_explicit_type2 type varchar(10) character set win1257 - ; - Result shows that column types NOT changed in this case and remains previous - FLD_DOMAIN_DEFINED VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI_AI Nullable // why not win1250 ? - FLD_EXPLICIT_TYPE1 VARCHAR(10) CHARACTER SET WIN1257 COLLATE WIN1257_EE Nullable // why not win1252 ? - FLD_EXPLICIT_TYPE2 VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI Nullable // why not win1257 ? - Sent report to Adriano, Dmitry et al, 05-oct-2023 08:18. Waiting for reply. + 2. There was issue about wrong change of columns collation, see: + https://github.com/FirebirdSQL/firebird/issues/7924 + Fixed in 6.0.0.219, commit: + https://github.com/FirebirdSQL/firebird/commit/11dec10f9fc079ed74d623211e01f465e45d6a7c + + [25.06.2025] pzotov + Minimal snapshot number for 6.x: 6.0.0.863, see letter to Adriano, 24.06.2025 11:05. Fixed in commit: + https://github.com/FirebirdSQL/firebird/commit/cbbbf3b94e7508806142eea0cd330ed4eedbbcdc + + Checked on 6.0.0.863; 3.0.13.33813. """ import pytest @@ -105,29 +103,6 @@ select 'domain_info, point-2' as msg, v.* from v_domain_info v; select 'table info, point-2' as msg, v.* from v_fields_info v; - - --------------------------------------------------------------- - - /* - !! TEMPORARY DISABLED. - !! LETTER TO ADRIANO, DIMITR ET AL, 05-OCT-2023 08:18. - !! WAITING FOR REPLY. - - alter domain dm_test type varchar(10) character set win1253; - - alter table test - alter column fld_domain_defined type varchar(10) character set win1250 - ,alter column fld_explicit_type1 type varchar(10) character set win1252 - ,alter column fld_explicit_type2 type varchar(10) character set win1257 - ; - commit; - - connect '$(DSN)'; - - select 'domain_info, point-3' as msg, v.* from v_domain_info v; - select 'table info, point-3' as msg, v.* from v_fields_info v; - */ - """ act = isql_act('db', test_script) From ee38d4c5e9dbbf41f6e52e78205a6ae9ab3fbe3c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 11:30:08 +0300 Subject: [PATCH 0662/1064] Added/Updated tests\bugs\core_1058_addi_test.py: Minimal snapshot number for 6.x: 6.0.0.863. See notes. --- tests/bugs/core_1058_addi_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_1058_addi_test.py b/tests/bugs/core_1058_addi_test.py index 6a56985b..895bd36d 100644 --- a/tests/bugs/core_1058_addi_test.py +++ b/tests/bugs/core_1058_addi_test.py @@ -18,8 +18,14 @@ FLD_DOMAIN_DEFINED VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI_AI Nullable // why not win1250 ? FLD_EXPLICIT_TYPE1 VARCHAR(10) CHARACTER SET WIN1257 COLLATE WIN1257_EE Nullable // why not win1252 ? FLD_EXPLICIT_TYPE2 VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI Nullable // why not win1257 ? - Initially report was sent to Adriano, Dmitry et al, 05-oct-2023 08:18. - Fix 22-JAN-2024 17:42 in: https://github.com/FirebirdSQL/firebird/commit/11dec10f9fc079ed74d623211e01f465e45d6a7c + Initially report was sent to Adriano, Dmitry et al, 05-oct-2023 08:18. + Fix 22-JAN-2024 17:42 in: https://github.com/FirebirdSQL/firebird/commit/11dec10f9fc079ed74d623211e01f465e45d6a7c + + [25.06.2025] pzotov + Minimal snapshot number for 6.x: 6.0.0.863, see letter to Adriano, 24.06.2025 11:05. Fixed in commit: + https://github.com/FirebirdSQL/firebird/commit/cbbbf3b94e7508806142eea0cd330ed4eedbbcdc + + Checked on 6.0.0.863; 3.0.13.33813. """ import pytest From ec42352bab3782b97349740372c52226c534ef33 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 11:35:41 +0300 Subject: [PATCH 0663/1064] Added/Updated tests\bugs\core_0856_test.py: Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0856_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_0856_test.py b/tests/bugs/core_0856_test.py index 81fe1e0d..e9ca1df4 100644 --- a/tests/bugs/core_0856_test.py +++ b/tests/bugs/core_0856_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-856 FBTEST: bugs.core_0856 +NOTES: + [25.06.2025] pzotov + Minimal snapshot number for 6.x: 6.0.0.863, see letter to Adriano, 24.06.2025 16:01. Fixed in commit: + https://github.com/FirebirdSQL/firebird/commit/b3da90583735da2b01c8c8129240cfffced6c1dc + + Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -24,7 +30,7 @@ set list on; select sec$user_name, sec$first_name, sec$middle_name, sec$last_name - from sec$users where upper(sec$user_name)=upper('tmp$c0856'); + from sec$users where upper(sec$user_name) = upper('tmp$c0856'); alter user tmp$c0856 firstname '' @@ -68,6 +74,6 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ec9ee39c28b659122b5986f20f9ec52784f2fc1e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 11:44:38 +0300 Subject: [PATCH 0664/1064] Added/Updated tests\bugs\core_1271_test.py: Minimal snapshot number for 6.x: 6.0.0.863. See notes. --- tests/bugs/core_1271_test.py | 49 +++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_1271_test.py b/tests/bugs/core_1271_test.py index adcb81e6..c3e15166 100644 --- a/tests/bugs/core_1271_test.py +++ b/tests/bugs/core_1271_test.py @@ -7,6 +7,15 @@ DESCRIPTION: JIRA: CORE-1271 FBTEST: bugs.core_1271 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Minimal snapshot number for 6.x: 6.0.0.863, see letter from Adriano, 24.06.2025 23:24, commit: + https://github.com/FirebirdSQL/firebird/commit/79ff650e5af7a0d6141e166b0cb8208ef211f0a7 + + Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,33 +24,43 @@ db = db_factory() test_script = """ + create table test(id int primary key using index test_id, f01 timestamp); + create index test_f01 on test(f01); + commit; set term ^; - create procedure p returns (out int) as + create procedure sp_test (a_id int) returns (o_f01 type of column test.f01) as begin - for - select rdb$relation_id - from rdb$relations - plan (rdb$relations order rdb$index_1) - order by rdb$description - into :out + for + select f01 from test where id = :a_id plan (test order test_f01) + into o_f01 do suspend; end ^ - commit^ + commit + ^ """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 2F000 - Error while parsing procedure P's BLR - -index RDB$INDEX_1 cannot be used in the specified plan + Error while parsing procedure SP_TEST's BLR + -index TEST_F01 cannot be used in the specified plan """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure "PUBLIC"."SP_TEST"'s BLR + -index "PUBLIC"."TEST_F01" cannot be used in the specified plan +""" + +expected_stdout = '' + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From bc4f85250859398ddc578f41083cfcbc6d500790 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 12:11:37 +0300 Subject: [PATCH 0665/1064] Added/Updated tests\bugs\core_0883_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0883_test.py | 341 ++++++++++++++++++++++++----------- 1 file changed, 235 insertions(+), 106 deletions(-) diff --git a/tests/bugs/core_0883_test.py b/tests/bugs/core_0883_test.py index 5fb07caa..9a578313 100644 --- a/tests/bugs/core_0883_test.py +++ b/tests/bugs/core_0883_test.py @@ -7,14 +7,52 @@ DESCRIPTION: JIRA: CORE-883 FBTEST: bugs.core_0883 +NOTES: + [25.06.2025] pzotov + Important change has performed vs previous version of this test: we *create* new database here instead of using .fbk + Additional lines present in BLR if we restore DB: + "blr_flags / blr_flags_search_system_cache, 0,0 / blr_end" + Sent letter to Adriano, 23.06.2025 17:07 + (subj: "BLR for stored procedure differs in 6.x depending on whether we create this SP in empty DB or this database was restored ...") + See replies from Adriano: 23.06.2025 17:28, 24.06.2025 14:39 (summary: these addtitional lines are *still* required). + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db = db_factory(from_backup='core0883-ods12.fbk') +db = db_factory() test_script = """ + set term ^; + create or alter procedure sp1 as + declare v_time time; + declare v_timestamp timestamp; + declare v_sp_id int; + declare v_src_text blob; + declare v_blr_text blob; + declare c_sttm cursor for ( + select p.rdb$procedure_id, p.rdb$procedure_source, p.rdb$procedure_blr + from rdb$procedures p + ); + begin + v_time = current_time (3); + v_timestamp = current_timestamp(3); + open c_sttm; + while (1=1) do + begin + fetch c_sttm into v_sp_id, v_src_text, v_blr_text; + if ( row_count = 0 ) then leave; + end + close c_sttm; + end ^ + set term ;^ + commit; + set list on; set blob all; select rdb$procedure_blr @@ -22,114 +60,205 @@ where rdb$procedure_name = upper('sp1'); """ -act = isql_act('db', test_script, substitutions=[('RDB\\$PROCEDURE_BLR.*', '')]) - -expected_stdout = """ -RDB$PROCEDURE_BLR 1a:f1 - blr_version5, - blr_begin, - blr_message, 1, 1,0, - blr_short, 0, - blr_begin, - blr_declare, 0,0, blr_sql_time, - blr_assignment, - blr_null, - blr_variable, 0,0, - blr_declare, 1,0, blr_timestamp, - blr_assignment, - blr_null, - blr_variable, 1,0, - blr_declare, 2,0, blr_long, 0, - blr_assignment, - blr_null, - blr_variable, 2,0, - blr_declare, 3,0, blr_blob2, 0,0, 0,0, - blr_assignment, - blr_null, - blr_variable, 3,0, - blr_declare, 4,0, blr_blob2, 0,0, 0,0, - blr_assignment, - blr_null, - blr_variable, 4,0, - blr_dcl_cursor, 0,0, - blr_rse, 1, - blr_relation2, 14, 'R','D','B','$','P','R','O','C','E','D','U','R','E','S', - 8, 'C','_','S','T','T','M',32,'P', 0, - blr_end, - 3,0, - blr_derived_expr, 1, 0, - blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', - blr_derived_expr, 1, 0, - blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', - blr_derived_expr, 1, 0, - blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', - blr_stall, - blr_label, 0, - blr_begin, - blr_begin, - blr_assignment, - blr_current_time2, 3, - blr_variable, 0,0, - blr_assignment, - blr_current_timestamp, - blr_variable, 1,0, - blr_cursor_stmt, 0, 0,0, +#act = isql_act('db', test_script, substitutions = [('[ \t]+', ' '), ('RDB\\$PROCEDURE_BLR.*', '')]) +act = isql_act('db', test_script, substitutions = [ ('RDB\\$PROCEDURE_BLR.*', '')]) - blr_begin, - blr_end, - blr_label, 1, - blr_loop, - blr_begin, - blr_if, - blr_eql, - blr_literal, blr_long, 0, 1,0,0,0, - blr_literal, blr_long, 0, 1,0,0,0, - blr_begin, - blr_begin, - blr_cursor_stmt, 2, 0,0, - - blr_begin, - blr_assignment, - blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', - blr_variable, 2,0, - blr_assignment, - blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', - blr_variable, 3,0, - blr_assignment, - blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', - blr_variable, 4,0, - blr_end, - blr_if, - blr_eql, - blr_internal_info, - blr_literal, blr_long, 0, 5,0,0,0, - blr_literal, blr_long, 0, 0,0,0,0, - blr_leave, 1, - blr_end, - blr_end, - blr_end, - blr_leave, 1, - blr_end, - blr_cursor_stmt, 1, 0,0, - - blr_begin, - blr_end, - blr_end, - blr_end, - blr_end, - blr_send, 1, - blr_begin, - blr_assignment, - blr_literal, blr_short, 0, 0,0, - blr_parameter, 1, 0,0, - blr_end, - blr_end, - blr_eoc +expected_stdout_5x = """ + RDB$PROCEDURE_BLR 1a:1e2 + blr_version5, + blr_begin, + blr_message, 1, 1,0, + blr_short, 0, + blr_begin, + blr_declare, 0,0, blr_sql_time, + blr_assignment, + blr_null, + blr_variable, 0,0, + blr_declare, 1,0, blr_timestamp, + blr_assignment, + blr_null, + blr_variable, 1,0, + blr_declare, 2,0, blr_long, 0, + blr_assignment, + blr_null, + blr_variable, 2,0, + blr_declare, 3,0, blr_blob2, 0,0, 0,0, + blr_assignment, + blr_null, + blr_variable, 3,0, + blr_declare, 4,0, blr_blob2, 0,0, 0,0, + blr_assignment, + blr_null, + blr_variable, 4,0, + blr_dcl_cursor, 0,0, + blr_rse, 1, + blr_relation2, 14, 'R','D','B','$','P','R','O','C','E','D','U','R','E','S', + 8, 'C','_','S','T','T','M',32,'P', 0, + blr_end, + 3,0, + blr_derived_expr, 1, 0, + blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', + blr_derived_expr, 1, 0, + blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', + blr_derived_expr, 1, 0, + blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', + blr_stall, + blr_label, 0, + blr_begin, + blr_begin, + blr_assignment, + blr_current_time2, 3, + blr_variable, 0,0, + blr_assignment, + blr_current_timestamp, + blr_variable, 1,0, + blr_cursor_stmt, 0, 0,0, + blr_label, 1, + blr_loop, + blr_begin, + blr_if, + blr_eql, + blr_literal, blr_long, 0, 1,0,0,0, + blr_literal, blr_long, 0, 1,0,0,0, + blr_begin, + blr_begin, + blr_cursor_stmt, 2, 0,0, + blr_begin, + blr_assignment, + blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', + blr_variable, 2,0, + blr_assignment, + blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', + blr_variable, 3,0, + blr_assignment, + blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', + blr_variable, 4,0, + blr_end, + blr_if, + blr_eql, + blr_internal_info, + blr_literal, blr_long, 0, 5,0,0,0, + blr_literal, blr_long, 0, 0,0,0,0, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_leave, 1, + blr_end, + blr_cursor_stmt, 1, 0,0, + blr_end, + blr_end, + blr_end, + blr_send, 1, + blr_begin, + blr_assignment, + blr_literal, blr_short, 0, 0,0, + blr_parameter, 1, 0,0, + blr_end, + blr_end, + blr_eoc """ +expected_stdout_6x = """ + RDB$PROCEDURE_BLR 1a:1e2 + blr_version5, + blr_begin, + blr_message, 1, 1,0, + blr_short, 0, + blr_begin, + blr_declare, 0,0, blr_sql_time, + blr_declare, 1,0, blr_timestamp, + blr_declare, 2,0, blr_long, 0, + blr_declare, 3,0, blr_blob2, 0,0, 0,0, + blr_declare, 4,0, blr_blob2, 0,0, 0,0, + blr_dcl_cursor, 0,0, + blr_rse, 1, + blr_relation3, + 6, 'S','Y','S','T','E','M', + 14, 'R','D','B','$','P','R','O','C','E','D','U','R','E','S', + 12, 34,'C','_','S','T','T','M',34,32,34,'P',34, + 0, + blr_end, + 3,0, + blr_derived_expr, 1, 0, + blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', + blr_derived_expr, 1, 0, + blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', + blr_derived_expr, 1, 0, + blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', + blr_assignment, + blr_null, + blr_variable, 0,0, + blr_assignment, + blr_null, + blr_variable, 1,0, + blr_assignment, + blr_null, + blr_variable, 2,0, + blr_assignment, + blr_null, + blr_variable, 3,0, + blr_assignment, + blr_null, + blr_variable, 4,0, + blr_stall, + blr_label, 0, + blr_begin, + blr_begin, + blr_assignment, + blr_current_time2, 3, + blr_variable, 0,0, + blr_assignment, + blr_current_timestamp, + blr_variable, 1,0, + blr_cursor_stmt, 0, 0,0, + blr_label, 1, + blr_loop, + blr_begin, + blr_if, + blr_eql, + blr_literal, blr_long, 0, 1,0,0,0, + blr_literal, blr_long, 0, 1,0,0,0, + blr_begin, + blr_begin, + blr_cursor_stmt, 2, 0,0, + blr_begin, + blr_assignment, + blr_field, 0, 16, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','I','D', + blr_variable, 2,0, + blr_assignment, + blr_field, 0, 20, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','S','O','U','R','C','E', + blr_variable, 3,0, + blr_assignment, + blr_field, 0, 17, 'R','D','B','$','P','R','O','C','E','D','U','R','E','_','B','L','R', + blr_variable, 4,0, + blr_end, + blr_if, + blr_eql, + blr_internal_info, + blr_literal, blr_long, 0, 5,0,0,0, + blr_literal, blr_long, 0, 0,0,0,0, + blr_leave, 1, + blr_end, + blr_end, + blr_end, + blr_leave, 1, + blr_end, + blr_cursor_stmt, 1, 0,0, + blr_end, + blr_end, + blr_end, + blr_send, 1, + blr_begin, + blr_assignment, + blr_literal, blr_short, 0, 0,0, + blr_parameter, 1, 0,0, + blr_end, + blr_end, + blr_eoc +""" @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 7b334ecb3c77ee6fa14ea2a65c80d708e40a2131 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 14:43:25 +0300 Subject: [PATCH 0666/1064] Added/Updated tests\bugs\core_5845_test.py: SEE NOTES. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5845_test.py | 112 +++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/tests/bugs/core_5845_test.py b/tests/bugs/core_5845_test.py index 309e4a8c..c7e75a82 100644 --- a/tests/bugs/core_5845_test.py +++ b/tests/bugs/core_5845_test.py @@ -9,25 +9,32 @@ FBTEST: bugs.core_5845 NOTES: [12.09.2023] pzotov - 1. Refactored: use firebird-driver ability to show plan (instead of call ISQL), removed hard-coded index names. - Expected result is "accumulated" by traversing through dictionary items (see 'chk_qry_map') instead of be written beforehand. - Added several queries provided by dimitr, letter 12-sep-2023. - - 2. ATTENTION: plan for query "select ... where t.id1 = 1 and t.x > 0 and t.id2 = 0" - has been changed in intermediate snapshot + 1. Added several queries provided by dimitr. + 2. Plan for query "select ... where t.id1 = 1 and t.x > 0 and t.id2 = 0" - has been changed in intermediate snapshot 5.0.0.1204 (timestamp: 20230912 08:00). One need to split expected results for FB 5.x+ and older versions. See: https://github.com/FirebirdSQL/firebird/commit/022f09287747dd05753bd11acd3b3fe4b0756f6e https://github.com/FirebirdSQL/firebird/compare/252c5b2b2f88...784f7bd8a6f5 - Checked on: 3.0.12.33707; 4.0.4.2986; 5.0.0.1204 (nightly build and intermediate snapshot of 12-sep-2023 08:00). + [25.06.2025] pzotov + 1. Re-implemented: use same Python dictionary which stores QUERIES as its KEYS and execution plans as values, + depending on major FB version. + 2. ::: ACHTUNG ::: + We have to call .free() in order to prevent from pytest hanging after all tests completed. + Workaround was provided by Vlad, letter 25.06.2025 13:36. + + 3. Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * P_KEY_IDX = "test_pk_id1_id2_id3".upper() -SINGLE_X_IDX = "test__x_only".upper() -COMPOUND_IDX = "test__id1_x".upper() +SINGLE_X_IDX = "test_single".upper() +COMPOUND_IDX = "test_compound".upper() init_sql = f""" recreate table test @@ -43,34 +50,61 @@ commit; """ -chk_qry_map_fb4 = { - "select * from test t where t.id1=1 and t.x>0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1=1 and t.x>0 order by t.id1, t.id2, t.id3" : f"PLAN SORT (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1=1 and t.x>0 order by t.id1+0, t.id2, t.id3" : f"PLAN SORT (T INDEX ({COMPOUND_IDX}))" - - # following examples were provided by dimitr, 12-sep-2023: - ,"select * from test t where t.id1 = 1 and t.x > 0 and t.id2 = 0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1 = 1 and t.x = 0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1 = 1 and t.id2 = 2" : f"PLAN (T INDEX ({P_KEY_IDX}))" - ,"select * from test t where t.id1 = 1 and t.id2 = 2 and t.id3 = 3" : f"PLAN (T INDEX ({P_KEY_IDX}))" - ,"select * from test t where t.id1 = 1 and t.x = 0 and t.id2 = 0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" -} - -chk_qry_map_fb5 = { - "select * from test t where t.id1=1 and t.x>0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1=1 and t.x>0 order by t.id1, t.id2, t.id3" : f"PLAN SORT (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1=1 and t.x>0 order by t.id1+0, t.id2, t.id3" : f"PLAN SORT (T INDEX ({COMPOUND_IDX}))" +chk_qry_map = { + "select * from test ta where ta.id1=1 and ta.x>0" : + ( + f"PLAN (TA INDEX ({COMPOUND_IDX}))", # 3.x ... 4.x + f"PLAN (TA INDEX ({COMPOUND_IDX}))", # 5.x + f'PLAN ("TA" INDEX ("PUBLIC"."{COMPOUND_IDX}"))', # 6.x+ + ) + ,"select * from test tb where tb.id1=1 and tb.x>0 order by tb.id1, tb.id2, tb.id3" : + ( + f"PLAN SORT (TB INDEX ({COMPOUND_IDX}))", + f"PLAN SORT (TB INDEX ({COMPOUND_IDX}))", + f'PLAN SORT ("TB" INDEX ("PUBLIC"."{COMPOUND_IDX}"))', + ) + ,"select * from test tc where tc.id1=1 and tc.x>0 order by tc.id1+0, tc.id2, tc.id3" : + ( + f"PLAN SORT (TC INDEX ({COMPOUND_IDX}))", + f"PLAN SORT (TC INDEX ({COMPOUND_IDX}))", + f'PLAN SORT ("TC" INDEX ("PUBLIC"."{COMPOUND_IDX}"))', + ) # following examples were provided by dimitr, 12-sep-2023: ########################################################## # ::: NB ::: Since 5.0.0.1204 (intermediate snapshot with timestamp 20230912 08:00) plan for following query # "select ... where t.id1 = 1 and t.x > 0 and t.id2 = 0" -- has been changed to: PLAN (T INDEX (TEST_PK_ID1_ID2_ID3)) ########################################################## - ,"select * from test t where t.id1 = 1 and t.x > 0 and t.id2 = 0" : f"PLAN (T INDEX ({P_KEY_IDX}))" - ,"select * from test t where t.id1 = 1 and t.x = 0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" - ,"select * from test t where t.id1 = 1 and t.id2 = 2" : f"PLAN (T INDEX ({P_KEY_IDX}))" - ,"select * from test t where t.id1 = 1 and t.id2 = 2 and t.id3 = 3" : f"PLAN (T INDEX ({P_KEY_IDX}))" - ,"select * from test t where t.id1 = 1 and t.x = 0 and t.id2 = 0" : f"PLAN (T INDEX ({COMPOUND_IDX}))" + ,"select * from test td where td.id1 = 1 and td.x > 0 and td.id2 = 0" : + ( + f"PLAN (TD INDEX ({COMPOUND_IDX}))", + f"PLAN (TD INDEX ({P_KEY_IDX}))", + f'PLAN ("TD" INDEX ("PUBLIC"."{P_KEY_IDX}"))', + ) + ,"select * from test te where te.id1 = 1 and te.x = 0" : + ( + f"PLAN (TE INDEX ({COMPOUND_IDX}))", + f"PLAN (TE INDEX ({COMPOUND_IDX}))", + f'PLAN ("TE" INDEX ("PUBLIC"."{COMPOUND_IDX}"))', + ) + ,"select * from test tf where tf.id1 = 1 and tf.id2 = 2" : + ( + f"PLAN (TF INDEX ({P_KEY_IDX}))", + f"PLAN (TF INDEX ({P_KEY_IDX}))", + f'PLAN ("TF" INDEX ("PUBLIC"."{P_KEY_IDX}"))', + ) + ,"select * from test tg where tg.id1 = 1 and tg.id2 = 2 and tg.id3 = 3" : + ( + f"PLAN (TG INDEX ({P_KEY_IDX}))", + f"PLAN (TG INDEX ({P_KEY_IDX}))", + f'PLAN ("TG" INDEX ("PUBLIC"."{P_KEY_IDX}"))', + ) + ,"select * from test th where th.id1 = 1 and th.x = 0 and th.id2 = 0" : + ( + f"PLAN (TH INDEX ({COMPOUND_IDX}))", + f"PLAN (TH INDEX ({COMPOUND_IDX}))", + f'PLAN ("TH" INDEX ("PUBLIC"."{COMPOUND_IDX}"))', + ) } db = db_factory(init = init_sql) @@ -79,18 +113,22 @@ @pytest.mark.version('>=3.0.4') def test_1(act: Action, capsys): - if act.is_version('<5'): - chk_qry_map = chk_qry_map_fb4 - else: - chk_qry_map = chk_qry_map_fb5 - expected_plans_lst = [ '\n'.join((k,v)) for k,v in chk_qry_map.items() ] + expected_plans_lst = [] with act.db.connect() as con: cur = con.cursor() - for q in chk_qry_map.keys(): + #for q in chk_qry_map.keys(): + for q, v in chk_qry_map.items(): + cur.execute(q) ps = cur.prepare(q) - print( q ) + print(q) print( ps.plan ) + + ps.free() # ::: achtung ::: 25.06.2024, need to prevent from pytest hanging after all tests completed. + + expected_qry_plan = v[0] if act.is_version('<5') else v[1] if act.is_version('<6') else v[2] + expected_plans_lst.append( q ) + expected_plans_lst.append( expected_qry_plan + '\n' ) act.expected_stdout = '\n'.join(expected_plans_lst) act.stdout = capsys.readouterr().out From c5a9a54692ef6149d65d5465262096c6e275173c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 14:45:22 +0300 Subject: [PATCH 0667/1064] Added/Updated tests\bugs\core_5845_test.py: minor change: added comment --- tests/bugs/core_5845_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_5845_test.py b/tests/bugs/core_5845_test.py index c7e75a82..ae648efe 100644 --- a/tests/bugs/core_5845_test.py +++ b/tests/bugs/core_5845_test.py @@ -22,6 +22,7 @@ 2. ::: ACHTUNG ::: We have to call .free() in order to prevent from pytest hanging after all tests completed. Workaround was provided by Vlad, letter 25.06.2025 13:36. + See also explaination by Vlad: 26.10.24 17:42 ("oddities when use instances of selective statements"). 3. Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. From 27a3f3a68617a026dbd6c5565bc428b6aac957b3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:18:05 +0300 Subject: [PATCH 0668/1064] Added/Updated tests\bugs\core_1271_test.py: minor change: removed old assignment --- tests/bugs/core_1271_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/bugs/core_1271_test.py b/tests/bugs/core_1271_test.py index c3e15166..814b5742 100644 --- a/tests/bugs/core_1271_test.py +++ b/tests/bugs/core_1271_test.py @@ -56,8 +56,6 @@ -index "PUBLIC"."TEST_F01" cannot be used in the specified plan """ -expected_stdout = '' - @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 4e8564a40051cf400beb8e1f6f5258ddb02ff151 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:26:21 +0300 Subject: [PATCH 0669/1064] Added/Updated tests\bugs\core_1401_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1401_test.py | 88 ++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/tests/bugs/core_1401_test.py b/tests/bugs/core_1401_test.py index e3dbf2d3..9b48882e 100644 --- a/tests/bugs/core_1401_test.py +++ b/tests/bugs/core_1401_test.py @@ -7,6 +7,15 @@ DESCRIPTION: JIRA: CORE-1401 FBTEST: bugs.core_1401 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Minimal snapshot number for 6.x: 6.0.0.863, see letter from Adriano, 24.06.2025 23:24, commit: + https://github.com/FirebirdSQL/firebird/commit/79ff650e5af7a0d6141e166b0cb8208ef211f0a7 + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,47 +23,56 @@ db = db_factory() -test_script = """create global temporary table t (f1 int, f2 int, f3 int); -create index idx1 on t (f1); -create index idx2 on t (f2); -create index idx3 on t (f3); -drop index idx2; - -set plan on; -insert into t values (1, 1, 1); -select * from t where f1 = 1; -select * from t where f2 = 1; -select * from t where f3 = 1; +test_script = """ + create global temporary table gtt_test (f1 int, f2 int, f3 int); + create index idx1 on gtt_test (f1); + create index idx2 on gtt_test (f2); + create index idx3 on gtt_test (f3); + drop index idx2; + set list on; + set plan on; + insert into gtt_test values (1, 1, 1); + select * from gtt_test where f1 = 1; + select * from gtt_test where f2 = 1; + select * from gtt_test where f3 = 1; """ -act = isql_act('db', test_script) - -expected_stdout = """ -PLAN (T INDEX (IDX1)) - - F1 F2 F3 -============ ============ ============ - 1 1 1 - - -PLAN (T NATURAL) - - F1 F2 F3 -============ ============ ============ - 1 1 1 - - -PLAN (T INDEX (IDX3)) - - F1 F2 F3 -============ ============ ============ - 1 1 1 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + PLAN (GTT_TEST INDEX (IDX1)) + F1 1 + F2 1 + F3 1 + PLAN (GTT_TEST NATURAL) + F1 1 + F2 1 + F3 1 + PLAN (GTT_TEST INDEX (IDX3)) + F1 1 + F2 1 + F3 1 +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."GTT_TEST" INDEX ("PUBLIC"."IDX1")) + F1 1 + F2 1 + F3 1 + PLAN ("PUBLIC"."GTT_TEST" NATURAL) + F1 1 + F2 1 + F3 1 + PLAN ("PUBLIC"."GTT_TEST" INDEX ("PUBLIC"."IDX3")) + F1 1 + F2 1 + F3 1 """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 112f1bf1b98e27185414592babc5664973b03b83 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:39:36 +0300 Subject: [PATCH 0670/1064] Minor change: fix wrong major version from list of checke snapshots. Group search and replace. --- tests/bugs/core_0059_test.py | 2 +- tests/bugs/core_0070_test.py | 2 +- tests/bugs/core_0104_test.py | 2 +- tests/bugs/core_0115_test.py | 2 +- tests/bugs/core_0116_test.py | 2 +- tests/bugs/core_0166_test.py | 2 +- tests/bugs/core_0196_test.py | 2 +- tests/bugs/core_0203_test.py | 50 +++++++++++------------------------- tests/bugs/core_0209_test.py | 2 +- tests/bugs/core_0223_test.py | 2 +- tests/bugs/core_0282_test.py | 2 +- tests/bugs/core_0304_test.py | 2 +- tests/bugs/core_0480_test.py | 2 +- tests/bugs/core_0501_test.py | 2 +- tests/bugs/core_0521_test.py | 2 +- tests/bugs/core_0583_test.py | 2 +- tests/bugs/core_0606_test.py | 2 +- tests/bugs/core_0625_test.py | 2 +- tests/bugs/core_0800_test.py | 2 +- tests/bugs/core_0847_test.py | 2 +- tests/bugs/core_0850_test.py | 2 +- tests/bugs/core_0851_test.py | 2 +- tests/bugs/core_0856_test.py | 2 +- tests/bugs/core_0866_test.py | 2 +- tests/bugs/core_0878_test.py | 2 +- tests/bugs/core_0879_test.py | 2 +- tests/bugs/core_0883_test.py | 2 +- tests/bugs/core_0885_test.py | 2 +- tests/bugs/core_0886_test.py | 2 +- tests/bugs/core_0899_test.py | 2 +- tests/bugs/core_0907_test.py | 2 +- tests/bugs/core_0908_test.py | 2 +- tests/bugs/core_0945_test.py | 2 +- tests/bugs/core_0995_test.py | 2 +- tests/bugs/core_1029_test.py | 2 +- tests/bugs/core_1056_test.py | 2 +- tests/bugs/core_1083_test.py | 2 +- tests/bugs/core_1090_test.py | 2 +- tests/bugs/core_1095_test.py | 2 +- tests/bugs/core_1145_test.py | 2 +- tests/bugs/core_1162_test.py | 2 +- tests/bugs/core_1165_test.py | 2 +- tests/bugs/core_1271_test.py | 2 +- tests/bugs/core_1291_test.py | 2 +- tests/bugs/core_1295_test.py | 2 +- tests/bugs/core_1316_test.py | 2 +- tests/bugs/core_1395_test.py | 2 +- tests/bugs/core_5236_test.py | 2 +- tests/bugs/core_5845_test.py | 2 +- 49 files changed, 63 insertions(+), 83 deletions(-) diff --git a/tests/bugs/core_0059_test.py b/tests/bugs/core_0059_test.py index 564e94ec..37cd12c3 100644 --- a/tests/bugs/core_0059_test.py +++ b/tests/bugs/core_0059_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0070_test.py b/tests/bugs/core_0070_test.py index 63d49905..409e9dfc 100644 --- a/tests/bugs/core_0070_test.py +++ b/tests/bugs/core_0070_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0104_test.py b/tests/bugs/core_0104_test.py index 38feb13c..b267aec3 100644 --- a/tests/bugs/core_0104_test.py +++ b/tests/bugs/core_0104_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0115_test.py b/tests/bugs/core_0115_test.py index a91a0586..7b4248f2 100644 --- a/tests/bugs/core_0115_test.py +++ b/tests/bugs/core_0115_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0116_test.py b/tests/bugs/core_0116_test.py index e5d3a982..936498ad 100644 --- a/tests/bugs/core_0116_test.py +++ b/tests/bugs/core_0116_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0166_test.py b/tests/bugs/core_0166_test.py index 58e7c848..68cc154a 100644 --- a/tests/bugs/core_0166_test.py +++ b/tests/bugs/core_0166_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0196_test.py b/tests/bugs/core_0196_test.py index e42257bb..9f8aa390 100644 --- a/tests/bugs/core_0196_test.py +++ b/tests/bugs/core_0196_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0203_test.py b/tests/bugs/core_0203_test.py index 343454aa..30afd700 100644 --- a/tests/bugs/core_0203_test.py +++ b/tests/bugs/core_0203_test.py @@ -17,6 +17,9 @@ See below example #4 for view v_test1 defined as "select * from ... plan (t natural)". JIRA: CORE-203 FBTEST: bugs.core_0203 +NOTES: + [22.06.2025] *** DEFERRED ***, SEE LETTER TO DIMITR AND ADRIANO. + https://github.com/FirebirdSQL/firebird/issues/8623 """ import pytest @@ -56,8 +59,9 @@ commit; + SET BAIL ON; + SET ECHO ON; set planonly; - --set echo on; select * from test t where x = 0 plan (t natural); -- 1 @@ -98,43 +102,19 @@ select * from v_test4 v4 PLAN (V4 V_TEST3 T INDEX (TEST_X_Y)); -- 16 """ -act = isql_act('db', test_script, substitutions=[('[ ]+', ' ')]) - -expected_stdout = """ - PLAN (T NATURAL) - - PLAN (V1 T INDEX (TEST_X_ASC)) - - PLAN (V2 T INDEX (TEST_X_ASC)) - - PLAN (V1 T NATURAL) - - PLAN (V2 T NATURAL) - - PLAN (V1 T INDEX (TEST_X_DESC)) - - PLAN (V2 T INDEX (TEST_X_DESC)) +# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings +# from act.files_dir/'test_config.ini': +# +addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] +addi_subst_tokens = addi_subst_settings['addi_subst'] - PLAN (V1 T INDEX (TEST_X_Y)) +substitutions = [('[ \t]+', ' ')] +#for p in addi_subst_tokens.split(' '): +# substitutions.append( (p, '') ) - PLAN (V2 T INDEX (TEST_Y_X)) - - PLAN (V1 T INDEX (TEST_X_Y)) - - PLAN (V2 T INDEX (TEST_X_Y)) - - PLAN (V1 T INDEX (TEST_SUM_X_Y)) - - PLAN (V2 T INDEX (TEST_SUB_X_Y)) - - PLAN (V3 T INDEX (TEST_X_ASC)) - - PLAN (V3 T INDEX (TEST_X_Y)) - - PLAN (V4 V_TEST3 T INDEX (TEST_X_ASC)) - - PLAN (V4 V_TEST3 T INDEX (TEST_X_Y)) +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout = """ """ @pytest.mark.version('>=3') diff --git a/tests/bugs/core_0209_test.py b/tests/bugs/core_0209_test.py index b4846731..cbd7ac9e 100644 --- a/tests/bugs/core_0209_test.py +++ b/tests/bugs/core_0209_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0223_test.py b/tests/bugs/core_0223_test.py index 4795295a..e26d62b0 100644 --- a/tests/bugs/core_0223_test.py +++ b/tests/bugs/core_0223_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0282_test.py b/tests/bugs/core_0282_test.py index 609b4bb8..218207e0 100644 --- a/tests/bugs/core_0282_test.py +++ b/tests/bugs/core_0282_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0304_test.py b/tests/bugs/core_0304_test.py index c77e2cf0..bcdd47a1 100644 --- a/tests/bugs/core_0304_test.py +++ b/tests/bugs/core_0304_test.py @@ -25,7 +25,7 @@ Adjusted explained plan in 6.x to actual. - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0480_test.py b/tests/bugs/core_0480_test.py index c4f5e670..2d85f570 100644 --- a/tests/bugs/core_0480_test.py +++ b/tests/bugs/core_0480_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0501_test.py b/tests/bugs/core_0501_test.py index f57c5d84..fb6e2b47 100644 --- a/tests/bugs/core_0501_test.py +++ b/tests/bugs/core_0501_test.py @@ -23,7 +23,7 @@ Also, for this test 'schema:' in SQLDA output is suppressed because as not relevant to check. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. JIRA: CORE-501 FBTEST: bugs.core_0501 """ diff --git a/tests/bugs/core_0521_test.py b/tests/bugs/core_0521_test.py index 66a86377..2f3488fa 100644 --- a/tests/bugs/core_0521_test.py +++ b/tests/bugs/core_0521_test.py @@ -9,7 +9,7 @@ FBTEST: bugs.core_0521 [23.06.2025] pzotov Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0583_test.py b/tests/bugs/core_0583_test.py index ec85fec1..4781665e 100644 --- a/tests/bugs/core_0583_test.py +++ b/tests/bugs/core_0583_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0606_test.py b/tests/bugs/core_0606_test.py index 87ca7af6..609486ea 100644 --- a/tests/bugs/core_0606_test.py +++ b/tests/bugs/core_0606_test.py @@ -12,7 +12,7 @@ Expected output was separated depending on FB version: we have to show SCHEMA name as prefix for DB object (since 6.0.0.834). Reimplemented: removed usage of hard-coded values for user and role name. Added substitutions to reduce irrelevant lines. - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0625_test.py b/tests/bugs/core_0625_test.py index 6628f75d..47532cfa 100644 --- a/tests/bugs/core_0625_test.py +++ b/tests/bugs/core_0625_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0800_test.py b/tests/bugs/core_0800_test.py index ec88fb60..030ba6fb 100644 --- a/tests/bugs/core_0800_test.py +++ b/tests/bugs/core_0800_test.py @@ -15,7 +15,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0847_test.py b/tests/bugs/core_0847_test.py index fdd8b63d..1d9d44e4 100644 --- a/tests/bugs/core_0847_test.py +++ b/tests/bugs/core_0847_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0850_test.py b/tests/bugs/core_0850_test.py index d473fcad..899b1382 100644 --- a/tests/bugs/core_0850_test.py +++ b/tests/bugs/core_0850_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0851_test.py b/tests/bugs/core_0851_test.py index f4bccd12..1aea6f16 100644 --- a/tests/bugs/core_0851_test.py +++ b/tests/bugs/core_0851_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0856_test.py b/tests/bugs/core_0856_test.py index e9ca1df4..5e134f70 100644 --- a/tests/bugs/core_0856_test.py +++ b/tests/bugs/core_0856_test.py @@ -12,7 +12,7 @@ Minimal snapshot number for 6.x: 6.0.0.863, see letter to Adriano, 24.06.2025 16:01. Fixed in commit: https://github.com/FirebirdSQL/firebird/commit/b3da90583735da2b01c8c8129240cfffced6c1dc - Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0866_test.py b/tests/bugs/core_0866_test.py index fbf24355..3d0189dd 100644 --- a/tests/bugs/core_0866_test.py +++ b/tests/bugs/core_0866_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0878_test.py b/tests/bugs/core_0878_test.py index 793ff7d5..be02d607 100644 --- a/tests/bugs/core_0878_test.py +++ b/tests/bugs/core_0878_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0879_test.py b/tests/bugs/core_0879_test.py index 3491cbe3..e31cda21 100644 --- a/tests/bugs/core_0879_test.py +++ b/tests/bugs/core_0879_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0883_test.py b/tests/bugs/core_0883_test.py index 9a578313..bc435bcd 100644 --- a/tests/bugs/core_0883_test.py +++ b/tests/bugs/core_0883_test.py @@ -19,7 +19,7 @@ Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. - Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0885_test.py b/tests/bugs/core_0885_test.py index e9ffc7af..4baf8d23 100644 --- a/tests/bugs/core_0885_test.py +++ b/tests/bugs/core_0885_test.py @@ -14,7 +14,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import locale diff --git a/tests/bugs/core_0886_test.py b/tests/bugs/core_0886_test.py index 0dd79008..f01c21c7 100644 --- a/tests/bugs/core_0886_test.py +++ b/tests/bugs/core_0886_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0899_test.py b/tests/bugs/core_0899_test.py index c29ef25b..690860ba 100644 --- a/tests/bugs/core_0899_test.py +++ b/tests/bugs/core_0899_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0907_test.py b/tests/bugs/core_0907_test.py index a0005bbb..fee0de1b 100644 --- a/tests/bugs/core_0907_test.py +++ b/tests/bugs/core_0907_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0908_test.py b/tests/bugs/core_0908_test.py index 8e58464d..7e08a265 100644 --- a/tests/bugs/core_0908_test.py +++ b/tests/bugs/core_0908_test.py @@ -17,7 +17,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0945_test.py b/tests/bugs/core_0945_test.py index 0aea17b3..23c92c0d 100644 --- a/tests/bugs/core_0945_test.py +++ b/tests/bugs/core_0945_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_0995_test.py b/tests/bugs/core_0995_test.py index b2710660..31932517 100644 --- a/tests/bugs/core_0995_test.py +++ b/tests/bugs/core_0995_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1029_test.py b/tests/bugs/core_1029_test.py index c4108f0e..16ec6afa 100644 --- a/tests/bugs/core_1029_test.py +++ b/tests/bugs/core_1029_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1056_test.py b/tests/bugs/core_1056_test.py index 064835d0..9a79977f 100644 --- a/tests/bugs/core_1056_test.py +++ b/tests/bugs/core_1056_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1083_test.py b/tests/bugs/core_1083_test.py index c105f277..3b7c18ef 100644 --- a/tests/bugs/core_1083_test.py +++ b/tests/bugs/core_1083_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1090_test.py b/tests/bugs/core_1090_test.py index d7ddb44b..52201828 100644 --- a/tests/bugs/core_1090_test.py +++ b/tests/bugs/core_1090_test.py @@ -14,7 +14,7 @@ See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md Previous test title: Error msg "Could not find UNIQUE INDEX" when in fact one is present [CORE1090] - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1095_test.py b/tests/bugs/core_1095_test.py index b89406a6..51059042 100644 --- a/tests/bugs/core_1095_test.py +++ b/tests/bugs/core_1095_test.py @@ -14,7 +14,7 @@ Also, for this test 'schema:' in SQLDA output is suppressed because as not relevant to check. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1145_test.py b/tests/bugs/core_1145_test.py index 96790e94..9efabd5c 100644 --- a/tests/bugs/core_1145_test.py +++ b/tests/bugs/core_1145_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1162_test.py b/tests/bugs/core_1162_test.py index e9aa88e1..0ead1ab1 100644 --- a/tests/bugs/core_1162_test.py +++ b/tests/bugs/core_1162_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.853; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.853; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1165_test.py b/tests/bugs/core_1165_test.py index f38150a4..96c450bb 100644 --- a/tests/bugs/core_1165_test.py +++ b/tests/bugs/core_1165_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1271_test.py b/tests/bugs/core_1271_test.py index 814b5742..71a17264 100644 --- a/tests/bugs/core_1271_test.py +++ b/tests/bugs/core_1271_test.py @@ -15,7 +15,7 @@ Minimal snapshot number for 6.x: 6.0.0.863, see letter from Adriano, 24.06.2025 23:24, commit: https://github.com/FirebirdSQL/firebird/commit/79ff650e5af7a0d6141e166b0cb8208ef211f0a7 - Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1291_test.py b/tests/bugs/core_1291_test.py index 3a9262af..30dbc412 100644 --- a/tests/bugs/core_1291_test.py +++ b/tests/bugs/core_1291_test.py @@ -10,7 +10,7 @@ NOTES: [24.06.2025] pzotov Added substitutions in orde to suppress output of procedure header info. This data irrelevant to the test. - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1295_test.py b/tests/bugs/core_1295_test.py index 6e411f94..e1f4d500 100644 --- a/tests/bugs/core_1295_test.py +++ b/tests/bugs/core_1295_test.py @@ -13,7 +13,7 @@ No substitutions are used to suppress schema name and quotes to enclosing object names. Discussed with dimitr, 24.06.2025 12:39. - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1316_test.py b/tests/bugs/core_1316_test.py index 443fb6c1..a9d80ee2 100644 --- a/tests/bugs/core_1316_test.py +++ b/tests/bugs/core_1316_test.py @@ -15,7 +15,7 @@ Adjusted explained plan in 6.x to actual. - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_1395_test.py b/tests/bugs/core_1395_test.py index d0ce6dd1..30e0aee9 100644 --- a/tests/bugs/core_1395_test.py +++ b/tests/bugs/core_1395_test.py @@ -13,7 +13,7 @@ SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output. See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_5236_test.py b/tests/bugs/core_5236_test.py index b04d5edc..3b1b451e 100644 --- a/tests/bugs/core_5236_test.py +++ b/tests/bugs/core_5236_test.py @@ -32,7 +32,7 @@ Adjusted explained plan in 6.x to actual. - Checked on 6.0.0.858; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.858; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest diff --git a/tests/bugs/core_5845_test.py b/tests/bugs/core_5845_test.py index ae648efe..0a37afbe 100644 --- a/tests/bugs/core_5845_test.py +++ b/tests/bugs/core_5845_test.py @@ -27,7 +27,7 @@ 3. Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. - Checked on 6.0.0.863; 6.0.3.1668; 4.0.6.3214; 3.0.13.33813. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest From 9a715a3121213139303010f5d9ca72e2f59ccee3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:44:31 +0300 Subject: [PATCH 0671/1064] Added/Updated tests\bugs\core_1482_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1482_test.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_1482_test.py b/tests/bugs/core_1482_test.py index 804e0a42..746d5e39 100644 --- a/tests/bugs/core_1482_test.py +++ b/tests/bugs/core_1482_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1482 FBTEST: bugs.core_1482 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -59,18 +65,24 @@ select * from tcolor m join thorses d on m.id = d.color_id order by d.id rows 1; """ -act = isql_act('db', test_script) -expected_stdout = """ - COLORS_CNT 50 - HORSES_CNT 50000 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout_5x = """ + COLORS_CNT 50 + HORSES_CNT 50000 PLAN JOIN (D ORDER THORSES_ID, M INDEX (TCOLOR_ID)) """ +expected_stdout_6x = """ + COLORS_CNT 50 + HORSES_CNT 50000 + PLAN JOIN ("D" ORDER "PUBLIC"."THORSES_ID", "M" INDEX ("PUBLIC"."TCOLOR_ID")) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From b71f4964594d936792a906ddb1deec48e0a3a4dd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:49:01 +0300 Subject: [PATCH 0672/1064] Added/Updated tests\bugs\core_1518_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1518_test.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_1518_test.py b/tests/bugs/core_1518_test.py index 07bb3414..76dd78ad 100644 --- a/tests/bugs/core_1518_test.py +++ b/tests/bugs/core_1518_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1518 FBTEST: bugs.core_1518 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -45,7 +51,7 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 22006 unsuccessful metadata update -Cannot make field C1 of table TEST NOT NULL because there are NULLs present @@ -63,9 +69,22 @@ -Cannot make field C3 of table TEST NOT NULL because there are NULLs present """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field "C1" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field "C1" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field "C2" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field "C3" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present +""" @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3a60c7dcf42b1460a90f5afce28a0316c13925c1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 18:58:24 +0300 Subject: [PATCH 0673/1064] Added/Updated tests\bugs\core_1525_test.py: Separated expected PLAN for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1525_test.py | 51 ++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_1525_test.py b/tests/bugs/core_1525_test.py index ebc87ede..0e85c85d 100644 --- a/tests/bugs/core_1525_test.py +++ b/tests/bugs/core_1525_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1525 FBTEST: bugs.core_1525 +NOTES: + [25.06.2025] pzotov + Separated expected PLAN for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -41,29 +47,34 @@ where cast ('2007-09-09' as date) < comp_last_day; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - ID 1 - LAST_DAY 2007-10-10 - COMP_LAST_DAY 2007-10-10 - ID 2 - LAST_DAY - COMP_LAST_DAY 2999-12-31 +@pytest.mark.version('>=2.0.7') +def test_1(act: Action): - PLAN (TEST_1 INDEX (IDX_1)) + # 25.06.2025 Separate PLAN depending on major FB version: + ########################## + expected_plan = 'PLAN (TEST_1 INDEX (IDX_1))' if act.is_version('<6') else 'PLAN ("PUBLIC"."TEST_1" INDEX ("PUBLIC"."IDX_1"))' - ID 1 - LAST_DAY 2007-10-10 - COMP_LAST_DAY 2007-10-10 - ID 2 - LAST_DAY - COMP_LAST_DAY 2999-12-31 -""" + expected_stdout = f""" + ID 1 + LAST_DAY 2007-10-10 + COMP_LAST_DAY 2007-10-10 + ID 2 + LAST_DAY + COMP_LAST_DAY 2999-12-31 + + {expected_plan} + + ID 1 + LAST_DAY 2007-10-10 + COMP_LAST_DAY 2007-10-10 + ID 2 + LAST_DAY + COMP_LAST_DAY 2999-12-31 + """ -@pytest.mark.version('>=2.0.7') -def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 2207e52e71c420d721d12f71249998355a187498 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 19:26:11 +0300 Subject: [PATCH 0674/1064] Added/Updated tests\bugs\core_1549_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1549_test.py | 338 +++++++++++++++++++++-------------- 1 file changed, 206 insertions(+), 132 deletions(-) diff --git a/tests/bugs/core_1549_test.py b/tests/bugs/core_1549_test.py index 29e0fece..00677906 100644 --- a/tests/bugs/core_1549_test.py +++ b/tests/bugs/core_1549_test.py @@ -7,157 +7,231 @@ DESCRIPTION: JIRA: CORE-1549 FBTEST: bugs.core_1549 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Re-implemented in order to preserve leading spaces in the explained plans output. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db = db_factory() - -test_script = """ +init_script = """ recreate table t(id int); commit; insert into t select row_number()over() from rdb$types a, (select 1 i from rdb$types rows 4) b rows 1000; commit; create index t_id on t(id); commit; - - -- Query-1: - set list on; - select '' as "EXISTS with ref. to 1st stream:" from rdb$database; - - set planonly; - set explain on; - - select a.id a_id, b.id b_id - from t a join t b on b.id >= a.id - where - not exists (select * from t x where x.id = a.id - 1) - and - not exists (select * from t z where z.id = b.id + 1); - - set planonly; - set plan off; - set explain off; - - select '' as "Two sep. DT and EXISTS inside:" from rdb$database; - - set planonly; - set explain on; - -- Query-2 - -- (serves as "etalone" -- how it should be in query-1): - select a.id a_id, b.id b_id - from ( - select t1.id - from t t1 - where - not exists (select * from t x where x.id = t1.id - 1) - ) a - join - ( - select t2.id - from t t2 - where - not exists (select * from t x where x.id = t2.id + 1) - ) b - on b.id >= a.id; """ +db = db_factory(init = init_script) -act = isql_act('db', test_script) +qry_map = { + 1000 : + ( + """ + select a.id a_id, b.id b_id + from t a join t b on b.id >= a.id + where + not exists (select * from t x where x.id = a.id - 1) + and + not exists (select * from t z where z.id = b.id + 1); + """ + , + "EXISTS() with reference to 1st stream" + ) + , + 2000 : + ( + """ + select a.id a_id, b.id b_id + from ( + select t1.id + from t t1 + where + not exists (select * from t x where x.id = t1.id - 1) + ) a + join + ( + select t2.id + from t t2 + where + not exists (select * from t x where x.id = t2.id + 1) + ) b + on b.id >= a.id + """ + , + 'Two separate derived tables and EXISTS() inside. Its plan must be considered as "etalone", i.e. how it should be in first the query' + ) +} + +act = python_act('db') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- -fb3x_expected_out = """ - EXISTS with ref. to 1st stream: +@pytest.mark.version('>=3.0') +def test_1(act: Action, capsys): + with act.db.connect() as con: + cur = con.cursor() + for qry_idx, qry_data in qry_map.items(): + test_sql, qry_comment = qry_data[:2] + ps, rs = None, None + try: + cur = con.cursor() + ps = cur.prepare(test_sql) + + print(qry_comment) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_out_3x = f""" + + {qry_map.get(1000)[1]} Select Expression - -> Filter - -> Table "T" as "X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) + ....-> Filter + ........-> Table "T" as "X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) Select Expression - -> Filter - -> Table "T" as "Z" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) + ....-> Filter + ........-> Table "T" as "Z" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) Select Expression - -> Nested Loop Join (inner) - -> Filter - -> Table "T" as "A" Full Scan - -> Filter - -> Table "T" as "B" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (lower bound: 1/1) - - - Two sep. DT and EXISTS inside: - + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "T" as "A" Full Scan + ........-> Filter + ............-> Table "T" as "B" Access By ID + ................-> Bitmap + ....................-> Index "T_ID" Range Scan (lower bound: 1/1) + + {qry_map.get(2000)[1]} Select Expression - -> Filter - -> Table "T" as "B X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) + ....-> Filter + ........-> Table "T" as "B X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) Select Expression - -> Filter - -> Table "T" as "A X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) + ....-> Filter + ........-> Table "T" as "A X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) Select Expression - -> Nested Loop Join (inner) - -> Filter - -> Table "T" as "A T1" Full Scan - -> Filter - -> Table "T" as "B T2" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (lower bound: 1/1) -""" - -fb5x_expected_out = """ - EXISTS with ref. to 1st stream: - - Sub-query - -> Filter - -> Table "T" as "X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) - Sub-query - -> Filter - -> Table "T" as "Z" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) - Select Expression - -> Nested Loop Join (inner) - -> Filter - -> Table "T" as "A" Full Scan - -> Filter - -> Table "T" as "B" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (lower bound: 1/1) - - Two sep. DT and EXISTS inside: - - - - Sub-query - -> Filter - -> Table "T" as "B X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) - Sub-query - -> Filter - -> Table "T" as "A X" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (full match) - Select Expression - -> Nested Loop Join (inner) - -> Filter - -> Table "T" as "A T1" Full Scan - -> Filter - -> Table "T" as "B T2" Access By ID - -> Bitmap - -> Index "T_ID" Range Scan (lower bound: 1/1) -""" -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = fb3x_expected_out if act.is_version('<5') else fb5x_expected_out - act.execute(combine_output = True) + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "T" as "A T1" Full Scan + ........-> Filter + ............-> Table "T" as "B T2" Access By ID + ................-> Bitmap + ....................-> Index "T_ID" Range Scan (lower bound: 1/1) + """ + + expected_out_5x = f""" + + {qry_map.get(1000)[1]} + Sub-query + ....-> Filter + ........-> Table "T" as "X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) + Sub-query + ....-> Filter + ........-> Table "T" as "Z" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "T" as "A" Full Scan + ........-> Filter + ............-> Table "T" as "B" Access By ID + ................-> Bitmap + ....................-> Index "T_ID" Range Scan (lower bound: 1/1) + + {qry_map.get(2000)[1]} + Sub-query + ....-> Filter + ........-> Table "T" as "B X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) + Sub-query + ....-> Filter + ........-> Table "T" as "A X" Access By ID + ............-> Bitmap + ................-> Index "T_ID" Range Scan (full match) + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "T" as "A T1" Full Scan + ........-> Filter + ............-> Table "T" as "B T2" Access By ID + ................-> Bitmap + ....................-> Index "T_ID" Range Scan (lower bound: 1/1) + """ + + expected_out_6x = f""" + + {qry_map.get(1000)[1]} + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."T" as "X" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."T_ID" Range Scan (full match) + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."T" as "Z" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."T_ID" Range Scan (full match) + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "PUBLIC"."T" as "A" Full Scan + ........-> Filter + ............-> Table "PUBLIC"."T" as "B" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."T_ID" Range Scan (lower bound: 1/1) + + {qry_map.get(2000)[1]} + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."T" as "B" "X" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."T_ID" Range Scan (full match) + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."T" as "A" "X" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."T_ID" Range Scan (full match) + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "PUBLIC"."T" as "A" "T1" Full Scan + ........-> Filter + ............-> Table "PUBLIC"."T" as "B" "T2" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."T_ID" Range Scan (lower bound: 1/1) + """ + + act.expected_stdout = expected_out_3x if act.is_version('<5') else expected_out_5x if act.is_version('<6') else expected_out_6x + + act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout - From 642a8ae7f3bc0e09979f68293e59d5b930b6d17f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 20:11:04 +0300 Subject: [PATCH 0675/1064] Added/Updated tests\bugs\core_1550_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1550_test.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_1550_test.py b/tests/bugs/core_1550_test.py index d26bf98d..ec333164 100644 --- a/tests/bugs/core_1550_test.py +++ b/tests/bugs/core_1550_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1550 FBTEST: bugs.core_1550 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,13 +37,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST ORDER TEST_ID) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_ID") +""" @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 42e07ed081401c62b04bd0e8ef2fc7a54bea47f8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 20:12:49 +0300 Subject: [PATCH 0676/1064] Updated tests\bugs\core_1550_postfix_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_1550_postfix_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_1550_postfix_test.py b/tests/bugs/core_1550_postfix_test.py index 3cce0b75..570e0154 100644 --- a/tests/bugs/core_1550_postfix_test.py +++ b/tests/bugs/core_1550_postfix_test.py @@ -88,8 +88,8 @@ def test_1(act: Action): """ else: expected_stdout = """ - PLAN HASH (M NATURAL, D ORDER TD_PK) - PLAN HASH (M NATURAL, D ORDER TD_F01_F02_UNQ) + PLAN HASH ("M" NATURAL, "D" ORDER "PUBLIC"."TD_PK") + PLAN HASH ("M" NATURAL, "D" ORDER "PUBLIC"."TD_F01_F02_UNQ") """ act.expected_stdout = expected_stdout From 7d4db957864bb9ae1e1f4f461649b5cdf493aec9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 20:16:49 +0300 Subject: [PATCH 0677/1064] Added/Updated tests\bugs\core_1559_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1559_test.py | 50 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_1559_test.py b/tests/bugs/core_1559_test.py index a9dd8ad3..92205677 100644 --- a/tests/bugs/core_1559_test.py +++ b/tests/bugs/core_1559_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1559 FBTEST: bugs.core_1559 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,35 +20,33 @@ db = db_factory() -test_script = """create table t (n integer constraint c not null); -COMMIT; -insert into t values (null); -COMMIT; -alter table t drop constraint c; -COMMIT; -insert into t values (null); -COMMIT; -SELECT * FROM t; +test_script = """ + set list on; + create table test (n integer constraint explicit_check_for_nn not null); + insert into test values (null); + commit; + alter table test drop constraint explicit_check_for_nn; + insert into test values (null); + select * from test; """ -act = isql_act('db', test_script) - -expected_stdout = """ - N -============ - +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) +expected_stdout_5x = """ + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."N", value "*** null ***" + N """ -expected_stderr = """Statement failed, SQLSTATE = 23000 -validation error for column "T"."N", value "*** null ***" +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."N", value "*** null ***" + N """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f90195f30de90bd5eced578d4d49df55d61f1324 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 20:23:18 +0300 Subject: [PATCH 0678/1064] Added/Updated tests\bugs\core_1592_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1592_test.py | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_1592_test.py b/tests/bugs/core_1592_test.py index 05f838d0..dc5f62bd 100644 --- a/tests/bugs/core_1592_test.py +++ b/tests/bugs/core_1592_test.py @@ -2,11 +2,19 @@ """ ID: issue-2013 -ISSUE: 2013 -TITLE: Altering procedure parameters can lead to unrestorable database +ISSUE: https://github.com/FirebirdSQL/firebird/issues/2013 +TITLE: Altering procedure parameters must be prohibited if there are dependent data in RDB$DEPENDENCIES DESCRIPTION: + Firebird should not allow the ALTER PROCEDURE statements if there are records in RDB$DEPENDENCIES + that reference a parameter that is not going to exists after the statement. JIRA: CORE-1592 FBTEST: bugs.core_1592 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -18,21 +26,21 @@ set bail on; set list on; set term ^; - create or alter procedure p2 as begin end + create or alter procedure sp_caller as begin end ^ commit ^ - create or alter procedure p1 returns ( x1 integer ) as begin + create or alter procedure sp_worker returns ( x1 integer ) as begin x1 = 10; suspend; end ^ - create or alter procedure p2 returns ( x1 integer ) as begin - for select x1 from p1 into :x1 do suspend; + create or alter procedure sp_caller returns ( x1 integer ) as begin + for select x1 from sp_worker into :x1 do suspend; end ^ -- This should FAIL and terminate script execution: - alter procedure p1 returns ( x2 integer ) as begin + alter procedure sp_worker returns ( x2 integer ) as begin x2 = 10; suspend; end ^ @@ -43,17 +51,24 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -PARAMETER SP_WORKER.X1 + -there are 1 dependencies +""" + +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -PARAMETER P1.X1 + -PARAMETER "PUBLIC"."SP_WORKER".X1 -there are 1 dependencies """ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0551ef47eb8031e661bc0846e7e41532397e023d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 20:48:58 +0300 Subject: [PATCH 0679/1064] Updated tests\bugs\core_1607_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_1607_test.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_1607_test.py b/tests/bugs/core_1607_test.py index 5faba98a..8b6dea45 100644 --- a/tests/bugs/core_1607_test.py +++ b/tests/bugs/core_1607_test.py @@ -63,13 +63,11 @@ def test_1(act: Action): """ else: expected_stdout = """ - PLAN (R RDB$DATABASE NATURAL) - PLAN HASH (R RDB$RELATIONS NATURAL, F NATURAL) - - PLAN HASH (R RDB$RELATIONS NATURAL, R RDB$RELATIONS NATURAL, F NATURAL) - - PLAN (R INDEX (RDB$INDEX_1)) - PLAN (D RDB$DATABASE NATURAL, D RDB$DATABASE NATURAL) + PLAN ("R" "SYSTEM"."RDB$DATABASE" NATURAL) + PLAN HASH ("R" "SYSTEM"."RDB$RELATIONS" NATURAL, "F" NATURAL) + PLAN HASH ("R" "SYSTEM"."RDB$RELATIONS" NATURAL, "R" "SYSTEM"."RDB$RELATIONS" NATURAL, "F" NATURAL) + PLAN ("R" INDEX ("SYSTEM"."RDB$INDEX_1")) + PLAN ("D" "SYSTEM"."RDB$DATABASE" NATURAL, "D" "SYSTEM"."RDB$DATABASE" NATURAL) """ act.expected_stdout = expected_stdout From 591e808d5f6fdd9e22437e5bb50ea4a146d434eb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 21:08:13 +0300 Subject: [PATCH 0680/1064] Added/Updated tests\bugs\core_1620_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1620_test.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_1620_test.py b/tests/bugs/core_1620_test.py index 3264150e..442cedca 100644 --- a/tests/bugs/core_1620_test.py +++ b/tests/bugs/core_1620_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1620 FBTEST: bugs.core_1620 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -26,9 +32,15 @@ execute procedure test_es1; """ -act = isql_act('db', test_script, substitutions=[("-At procedure 'TEST_ES1' line:.*", '')]) +# ::: ACHTUNG ::: +# DO NOT use any substitutions here! +# We have to check EXACTLY that error message contains +# proper (adequate) column value in: +# "-Unexpected end of command - line 1, column 1" +# +act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Dynamic SQL Error -SQL error code = -104 @@ -36,9 +48,16 @@ -At procedure 'TEST_ES1' line: 3, col: 9 """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Unexpected end of command - line 1, column 1 + -At procedure "PUBLIC"."TEST_ES1" line: 3, col: 9 +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 53c52bd10f985bed6dcbe869e054e21c203d170b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 21:13:14 +0300 Subject: [PATCH 0681/1064] Added/Updated tests\bugs\core_1689_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1689_test.py | 40 ++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_1689_test.py b/tests/bugs/core_1689_test.py index 389b38d2..bbc84d8b 100644 --- a/tests/bugs/core_1689_test.py +++ b/tests/bugs/core_1689_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1689 FBTEST: bugs.core_1689 +NOTES: + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -44,12 +50,15 @@ -there are 4 dependencies """ + @pytest.mark.version('>=3.0,<4.0') def test_1(act_1: Action): act_1.expected_stderr = expected_stderr_1 act_1.execute() assert act_1.clean_stderr == act_1.clean_expected_stderr +######################################################################################### + # version: 4.0 db_2 = db_factory() @@ -108,17 +117,26 @@ def test_1(act_1: Action): act_2 = isql_act('db_2', test_script_2) -expected_stderr_2 = """ - Statement failed, SQLSTATE = 38000 - unsuccessful metadata update - -cannot delete - -Function UDR40_GETEXACTTIMESTAMPUTC - -there are 6 dependencies -""" - @pytest.mark.version('>=4.0') def test_2(act_2: Action): - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert act_2.clean_stderr == act_2.clean_expected_stderr + if act_2.is_version('<6'): + expected_stdout = """ + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function UDR40_GETEXACTTIMESTAMPUTC + -there are 6 dependencies + """ + else: + expected_stdout = """ + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function "PUBLIC"."UDR40_GETEXACTTIMESTAMPUTC" + -there are 6 dependencies + """ + + act_2.expected_stdout = expected_stdout + act_2.execute(combine_output = True) + assert act_2.clean_stdout == act_2.clean_expected_stdout From 9032cdef675b2ba4358d24c3fdd8b30c23a189cb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 21:43:36 +0300 Subject: [PATCH 0682/1064] Added/Updated tests\bugs\core_1690_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1690_test.py | 58 ++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_1690_test.py b/tests/bugs/core_1690_test.py index 9db71151..a6f08b16 100644 --- a/tests/bugs/core_1690_test.py +++ b/tests/bugs/core_1690_test.py @@ -7,29 +7,55 @@ DESCRIPTION: JIRA: CORE-1690 FBTEST: bugs.core_1690 -""" +NOTES: + [25.06.2025] pzotov + Re-implemented: non-ascii names are used for created table and its column, with max allowed length + for utf8 charset to prevent "Name longer than database column size" error. -import pytest -from firebird.qa import * + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. -init_script = """create table A (C1 INTEGER PRIMARY KEY); + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ -db = db_factory(charset='UTF8', init=init_script) - -test_script = """show table A; -""" +import pytest +from firebird.qa import * -act = isql_act('db', test_script) +db = db_factory(charset='utf8') -expected_stdout = """C1 INTEGER Not Null -CONSTRAINT INTEG_2: - Primary key (C1) -""" +substitutions = [('[ \t]+', ' '), ('Table:.*', ''), ('CONSTRAINT INTEG_\\d+', 'CONSTRAINT INTEG')] +act = isql_act('db', substitutions = substitutions) @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + if act.is_version('<4'): + # We have ti limit names by 16 unicode characters otherwise get: + # "SQLSTATE = 42000 / -Name longer than database column size" + TABLE_NAME = 'àáâãäåæçèéêëìíî' + FIELD_NAME = 'ÐÑÒÓÔÕÖרÙÚÛÜÝÞ' + else: + TABLE_NAME = 'àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ' + FIELD_NAME = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ' + + test_script = f""" + create table "{TABLE_NAME}" ("{FIELD_NAME}" int primary key); + show table "{TABLE_NAME}"; + """ + + expected_stdout_5x = f""" + {FIELD_NAME} INTEGER Not Null + CONSTRAINT INTEG_2: + Primary key ({FIELD_NAME}) + """ + + # NB: Names of table and field are enclosed in double quotes in FB 6.x (since 6.0.0.834): + expected_stdout_6x = f""" + "{FIELD_NAME}" INTEGER Not Null + CONSTRAINT INTEG_2: + Primary key ("{FIELD_NAME}") + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + #act.execute(combine_output = True) + act.isql(switches = ['-q'], charset = 'utf8', input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 3559be1d3b88affa4256b4ec567dec0b4caa8e60 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 25 Jun 2025 22:08:21 +0300 Subject: [PATCH 0683/1064] Added/Updated tests\bugs\core_1694_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1694_test.py | 167 ++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 80 deletions(-) diff --git a/tests/bugs/core_1694_test.py b/tests/bugs/core_1694_test.py index bffd5fc1..5dfbd77d 100644 --- a/tests/bugs/core_1694_test.py +++ b/tests/bugs/core_1694_test.py @@ -7,6 +7,15 @@ DESCRIPTION: JIRA: CORE-1694 FBTEST: bugs.core_1694 +NOTES: + [25.06.2025] pzotov + Re-implemented: use variables for storing non-ascii text and f-notation to sustitute them. + Use alternate string quoting to avoid duplicating of apostrophes inside statement passed to ES. + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,33 +23,22 @@ db = db_factory(charset='UTF8') -test_script = """ -create domain varchar_domain as varchar(50) character set utf8 collate utf8; -create domain varchar_domain2 as varchar(50) character set utf8 collate utf8; -commit; - -set term ^; -execute block as -begin -execute statement ' -create or alter trigger trg_conn active on connect position 0 -as +HEAD_COMMENT_1 = """ /* — Eh bien, mon prince. Gênes et Lucques ne sont plus que des apanages, des поместья, de la famille Buonaparte. Non, je vous préviens que si vous ne me dites pas que nous avons la guerre, si vous vous permettez encore de pallier toutes les infamies, toutes - les atrocités de cet Antichrist (ma parole, j''y crois) — je ne vous connais plus, vous - n''êtes plus mon ami, vous n''êtes plus мой верный раб, comme vous dites. + les atrocités de cet Antichrist (ma parole, j'y crois) — je ne vous connais plus, vous + n'êtes plus mon ami, vous n'êtes plus мой верный раб, comme vous dites. Ну, здравствуйте, здравствуйте. Je vois que je vous fais peur, садитесь и рассказывайте. Так говорила в июле 1805 года известная Анна Павловна Шерер, фрейлина и приближенная императрицы Марии Феодоровны, встречая важного и чиновного князя Василия, первого приехавшего на ее вечер. Анна Павловна кашляла несколько дней, у нее был грипп, как она говорила (грипп был тогда новое слово, употреблявшееся только редкими). */ - declare u int; - declare variable new_var1 varchar(50) character set utf8 collate utf8 default ''Que voulez-vous ?''; - declare variable new_var3 type of varchar_domain default ''Что делать ?''; - declare variable new_var4 type of varchar_domain2 default ''Кто виноват ?''; +""" + +HEAD_COMMENT_2 = """ /* Dieu, quelle virulente sortie! 4 — отвечал, нисколько не смутясь такою встречей, вошедший князь, в придворном, шитом мундире, в чулках, башмаках и звездах, с светлым выражением @@ -49,105 +47,114 @@ состаревшемуся в свете и при дворе значительному человеку. Он подошел к Анне Павловне, поцеловал ее руку, подставив ей свою надушенную и сияющую лысину, и покойно уселся на диване. */ - declare v int = 2; +""" + +HEAD_COMMENT_3 = """ /* - — Ne me tourmentez pas. Eh bien, qu''a-t-on décidé par rapport à la dépêche de Novosilzoff? + — Ne me tourmentez pas. Eh bien, qu'a-t-on décidé par rapport à la dépêche de Novosilzoff? Vous savez tout. - — Как вам сказать? — сказал князь холодным, скучающим тоном. — Qu''a-t-on décidé? On a décidé + — Как вам сказать? — сказал князь холодным, скучающим тоном. — Qu'a-t-on décidé? On a décidé que Buonaparte a brûlé ses vaisseaux, et je crois que nous sommes en train de brûler les nôtres 8. Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. */ - declare w int = 3; -begin - u = +""" + +BODY_COMMENT_1 = """ /* Ах, не говорите мне про Австрию! Я ничего не понимаю, может быть, но Австрия никогда не хотела и не хочет войны. Она предает нас. Россия одна должна быть спасительницей Европы. Наш благодетель знает свое высокое призвание и будет верен ему. Вот одно, во что я верю. Нашему доброму и чудному */ - v + +""" + +BODY_COMMENT_2 = """ /*государю предстоит величайшая роль в мире, и он так добродетелен и хорош, что Бог не оставит его, и он исполнит свое призвание задавить гидру революции, которая теперь еще ужаснее в лице этого убийцы и злодея. Мы одни должны искупить кровь праведника. На кого нам надеяться, я вас спрашиваю?.. */ - w; +""" + +BODY_COMMENT_3 = """ /* Англия с своим коммерческим духом не поймет и не может понять всю высоту души императора Александра */ -end' -; -end -^ -set term ;^ -commit; - -show trigger trg_conn; """ -act = isql_act('db', test_script, - substitutions=[('[+++].*', ''), ('[===].*', ''), ('Trigger text.*', '')]) +test_script = f""" +create domain varchar_domain as varchar(50) character set utf8 collate utf8; +create domain varchar_domain2 as varchar(50) character set utf8 collate utf8; +commit; -expected_stdout = """ -TRG_CONN, Sequence: 0, Type: ON CONNECT, Active +set term ^; +execute block as +begin +-- ############################################################################### +-- ### u s e `q' ` ### +-- ### see: $FB_HOME/doc/sql.extensions/README.alternate_string_quoting.txt ### +-- ############################################################################### +execute statement q'# +create or alter trigger trg_conn active on connect position 0 as - /* - — Eh bien, mon prince. Gênes et Lucques ne sont plus que des apanages, des поместья, - de la famille Buonaparte. Non, je vous préviens que si vous ne me dites pas que nous - avons la guerre, si vous vous permettez encore de pallier toutes les infamies, toutes - les atrocités de cet Antichrist (ma parole, j'y crois) — je ne vous connais plus, vous - n'êtes plus mon ami, vous n'êtes plus мой верный раб, comme vous dites. - Ну, здравствуйте, здравствуйте. Je vois que je vous fais peur, садитесь и рассказывайте. - Так говорила в июле 1805 года известная Анна Павловна Шерер, фрейлина и приближенная - императрицы Марии Феодоровны, встречая важного и чиновного князя Василия, первого - приехавшего на ее вечер. Анна Павловна кашляла несколько дней, у нее был грипп, как она - говорила (грипп был тогда новое слово, употреблявшееся только редкими). - */ + {HEAD_COMMENT_1} declare u int; declare variable new_var1 varchar(50) character set utf8 collate utf8 default 'Que voulez-vous ?'; declare variable new_var3 type of varchar_domain default 'Что делать ?'; declare variable new_var4 type of varchar_domain2 default 'Кто виноват ?'; - /* - Dieu, quelle virulente sortie! 4 — отвечал, нисколько не смутясь такою встречей, вошедший - князь, в придворном, шитом мундире, в чулках, башмаках и звездах, с светлым выражением - плоского лица. Он говорил на том изысканном французском языке, на котором не только говорили, - но и думали наши деды, и с теми, тихими, покровительственными интонациями, которые свойственны - состаревшемуся в свете и при дворе значительному человеку. Он подошел к Анне Павловне, - поцеловал ее руку, подставив ей свою надушенную и сияющую лысину, и покойно уселся на диване. - */ + {HEAD_COMMENT_2} declare v int = 2; - /* - — Ne me tourmentez pas. Eh bien, qu'a-t-on décidé par rapport à la dépêche de Novosilzoff? - Vous savez tout. - — Как вам сказать? — сказал князь холодным, скучающим тоном. — Qu'a-t-on décidé? On a décidé - que Buonaparte a brûlé ses vaisseaux, et je crois que nous sommes en train de brûler les nôtres 8. - Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, - напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. - */ + {HEAD_COMMENT_3} declare w int = 3; begin u = - /* - Ах, не говорите мне про Австрию! Я ничего не понимаю, может быть, но Австрия никогда не хотела - и не хочет войны. Она предает нас. Россия одна должна быть спасительницей Европы. Наш благодетель - знает свое высокое призвание и будет верен ему. Вот одно, во что я верю. Нашему доброму и чудному - */ + {BODY_COMMENT_1} v + - /*государю предстоит величайшая роль в мире, и он так добродетелен и хорош, что Бог не оставит его, - и он исполнит свое призвание задавить гидру революции, которая теперь еще ужаснее в лице этого - убийцы и злодея. Мы одни должны искупить кровь праведника. На кого нам надеяться, я вас спрашиваю?.. - */ + {BODY_COMMENT_2} w; - /* - Англия с своим коммерческим духом не поймет и не может понять всю высоту души императора Александра - */ + {BODY_COMMENT_3} +end#' +; end -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^ +set term ;^ +commit; + +show trigger trg_conn; """ +act = isql_act('db', test_script, + substitutions=[('[+++].*', ''), ('[===].*', ''), ('Trigger text.*', '')]) + @pytest.mark.version('>=3') def test_1(act: Action): + + # 25.06.2025: name of DB objects now have schema prefix (since 6.0.0.834): + # + TRG_NAME = 'TRG_CONN' if act.is_version('<6') else 'PUBLIC.TRG_CONN' + + expected_stdout = f""" + {TRG_NAME}, Sequence: 0, Type: ON CONNECT, Active + as + {HEAD_COMMENT_1} + declare u int; + declare variable new_var1 varchar(50) character set utf8 collate utf8 default 'Que voulez-vous ?'; + declare variable new_var3 type of varchar_domain default 'Что делать ?'; + declare variable new_var4 type of varchar_domain2 default 'Кто виноват ?'; + {HEAD_COMMENT_2} + declare v int = 2; + {HEAD_COMMENT_3} + declare w int = 3; + begin + u = + {BODY_COMMENT_1} + v + + {BODY_COMMENT_2} + w; + {BODY_COMMENT_3} + end + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + """ + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 3bea268c969e68c28ab051e38445d3ee0fd01af5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 00:22:27 +0300 Subject: [PATCH 0684/1064] Added/Updated tests\bugs\core_1715_test.py: Re-implemented: use max allowed values of key lengths for indices when 4 and 6 bytes are used per character. Checked on 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. FOUND ISSUE FOR FB 6.X, will be completed after fix (sent report to Adriano). --- tests/bugs/core_1715_test.py | 86 +++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_1715_test.py b/tests/bugs/core_1715_test.py index b33f0082..7a94e6cb 100644 --- a/tests/bugs/core_1715_test.py +++ b/tests/bugs/core_1715_test.py @@ -7,36 +7,78 @@ DESCRIPTION: JIRA: CORE-1715 FBTEST: bugs.core_1715 +NOTES: + [26.06.2025] pzotov + Re-implemented: use max allowed values of key lengths for indices when 4 and 6 bytes are used per character. + See: + https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html#fblangref50-ddl-idx-limits + ("Table 38. Maximum indexable (VAR)CHAR length") + Checked on 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + + ::: NB ::: + FB 6.x: it seems that since '4fe307: Improvement #8406 - Increase MIN_PAGE_SIZE to 8192' we can NOT create DB with any size except 8192. + Sent report to Adriano, 26.06.2025 00:13. WAITING FOR REPLY. + + ### QA TODO. DEFERRED FOR FB 6.X ### + """ +from pathlib import Path +import locale import pytest from firebird.qa import * -init_script = """create table t1 ( - t1_id integer not null - , vc_50_utf8_utf8 varchar(253) character set utf8 collate utf8 - , vc_50_utf8_unicode varchar(169) character set utf8 collate unicode - , constraint pk_t1_id primary key (t1_id) -);""" +db = db_factory(charset='utf8') -db = db_factory(charset='UTF8', init=init_script) +substitutions = [('[ \t]+', ' ')] +act = python_act('db', substitutions = substitutions) -test_script = """create index i_vc_50_utf8_unicode on t1 (vc_50_utf8_unicode); -create index i_vc_50_utf8_utf8 on t1 (vc_50_utf8_utf8); -commit; -show index; -""" +tmp_fdb = temp_file('tmp_core_1715.fdb') -act = isql_act('db', test_script) +@pytest.mark.version('>=3,<6') +def test_1(act: Action, tmp_fdb: Path, capsys): + + utf8_max_key_size_map = {4096 : (253, 169), 8192 : (509,339), 16384 : (1021,681)} + if act.is_version('>=6'): + del utf8_max_key_size_map[4096] + utf8_max_key_size_map[32768] = (2045, 1363) -expected_stdout = """I_VC_50_UTF8_UNICODE INDEX ON T1(VC_50_UTF8_UNICODE) -I_VC_50_UTF8_UTF8 INDEX ON T1(VC_50_UTF8_UTF8) -PK_T1_ID UNIQUE INDEX ON T1(T1_ID) -""" + expected_lst = [] + for pg_size, max_key_length_pair in utf8_max_key_size_map.items(): -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout + tmp_fdb.unlink(missing_ok = True) + + max_key_4_bytes_per_char, max_key_6_bytes_per_char = max_key_length_pair[:2] + passed_msg = f'Passed for {max_key_length_pair=}' + test_script = f""" + set bail on; + set list on; + create database 'localhost:{str(tmp_fdb)}' + page_size {pg_size} + default character set utf8 + ; + select mon$page_size from mon$database; + commit; + create table test ( + vc_utf8_utf8 varchar({max_key_4_bytes_per_char}) character set utf8 collate utf8 + ,vc_utf8_unic varchar({max_key_6_bytes_per_char}) character set utf8 collate unicode + ); + create index i_vc_utf8 on test (vc_utf8_utf8); + create index i_vc_unic on test (vc_utf8_unic); + commit; + set list off; + set heading off; + select '{passed_msg}' from rdb$database; + drop database; + """ + + act.isql(switches=['-q'], input = test_script, credentials = True, charset = 'utf8', connect_db = False, combine_output = True, io_enc = locale.getpreferredencoding()) + print(act.clean_stdout) + act.reset() + + expected_lst.extend( [f'mon$page_size {pg_size}'.upper(), passed_msg] ) + + act.expected_stdout = '\n'.join(expected_lst) + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout From 52c8e956074c46a346d963594ca90a68838d27b0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 00:25:49 +0300 Subject: [PATCH 0685/1064] Added/Updated tests\bugs\core_1746_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_1746_test.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_1746_test.py b/tests/bugs/core_1746_test.py index 4e8a1b8c..826b3271 100644 --- a/tests/bugs/core_1746_test.py +++ b/tests/bugs/core_1746_test.py @@ -17,8 +17,10 @@ On 2.5.3.26780 and 3.0.0.32483 statement 'create index' will pass (and this must be considered as problem). On 2.5.27020 and 3.0.1 such attempt leads to exception "-901 / object ... in use" - and this is expected. See also core_4386_test.py. - - Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 (SS/CS) + Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 (SS/CS) + [25.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -62,14 +64,22 @@ def test_1(act: Action, capsys): print(e.__str__()) print(e.gds_codes) - expected_fail = """ - lock conflict on no wait transaction - -unsuccessful metadata update - -object TABLE "TEST" is in use - (335544345, 335544351, 335544453) - """ + if act.is_version('<6'): + expected_out = """ + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "TEST" is in use + (335544345, 335544351, 335544453) + """ + else: + expected_out = """ + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "PUBLIC"."TEST" is in use + (335544345, 335544351, 335544453) + """ - act.expected_stdout = expected_fail + act.expected_stdout = expected_out act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout act.reset() From 5749522364705b3eb953968bdac7d366a13e4c25 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 00:33:22 +0300 Subject: [PATCH 0686/1064] Added/Updated tests\bugs\core_1760_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1760_test.py | 272 ++++++++++++++++++++++------------- 1 file changed, 173 insertions(+), 99 deletions(-) diff --git a/tests/bugs/core_1760_test.py b/tests/bugs/core_1760_test.py index 9f558feb..3803ddeb 100644 --- a/tests/bugs/core_1760_test.py +++ b/tests/bugs/core_1760_test.py @@ -7,6 +7,12 @@ DESCRIPTION: See doc\\sql.extensions\\README.hex_literals.txt JIRA: CORE-1760 FBTEST: bugs.core_1760 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -72,107 +78,175 @@ act = isql_act('db', test_script, substitutions=[('.*At line.*', ''), ('-Token unknown.*', '-Token unknown')]) -expected_stdout = """ -CONSTANT 11 -CONSTANT 0123456789 -CONSTANT 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -UUID_TO_CHAR BA1749B5-83BF-9146-B360-F54E25FE583E --1(a) -1 -+15 15 -32767 32767 -32768 32768 -65535 65535 -65536(a) 65536 -65536(b) 65536 --2147483648 -2147483648 -+2147483648(a) 2147483648 -+2147483648(b) 2147483648 --1(b) -1 -+4294967295 4294967295 -+4294967296(a) 4294967296 -+4294967296(b) 4294967296 -9223372036854775807 9223372036854775807 --9223372036854775808 -9223372036854775808 --9223372036854775807 -9223372036854775807 --9223372036854775806 -9223372036854775806 --1(c) -1 -INPUT message field count: 0 -OUTPUT message field count: 19 -01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: -1(a) alias: -1(a) - : table: V_TEST owner: SYSDBA -02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: +15 alias: +15 - : table: V_TEST owner: SYSDBA -03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: 32767 alias: 32767 - : table: V_TEST owner: SYSDBA -04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: 32768 alias: 32768 - : table: V_TEST owner: SYSDBA -05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: 65535 alias: 65535 - : table: V_TEST owner: SYSDBA -06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: 65536(a) alias: 65536(a) - : table: V_TEST owner: SYSDBA -07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: 65536(b) alias: 65536(b) - : table: V_TEST owner: SYSDBA -08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: -2147483648 alias: -2147483648 - : table: V_TEST owner: SYSDBA -09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: +2147483648(a) alias: +2147483648(a) - : table: V_TEST owner: SYSDBA -10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: +2147483648(b) alias: +2147483648(b) - : table: V_TEST owner: SYSDBA -11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: -1(b) alias: -1(b) - : table: V_TEST owner: SYSDBA -12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: +4294967295 alias: +4294967295 - : table: V_TEST owner: SYSDBA -13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: +4294967296(a) alias: +4294967296(a) - : table: V_TEST owner: SYSDBA -14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: +4294967296(b) alias: +4294967296(b) - : table: V_TEST owner: SYSDBA -15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: 9223372036854775807 alias: 9223372036854775807 - : table: V_TEST owner: SYSDBA -16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: -9223372036854775808 alias: -9223372036854775808 - : table: V_TEST owner: SYSDBA -17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: -9223372036854775807 alias: -9223372036854775807 - : table: V_TEST owner: SYSDBA -18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: -9223372036854775806 alias: -9223372036854775806 - : table: V_TEST owner: SYSDBA -19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: -1(c) alias: -1(c) - : table: V_TEST owner: SYSDBA -""" - -expected_stderr = """ -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Token unknown - line 1, column 9 --'1' - -Statement failed, SQLSTATE = 42000 -Dynamic SQL Error --SQL error code = -104 --Token unknown - line 1, column 9 --'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x' -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): + if act.is_version('<6'): + expected_sqlda = """ + INPUT message field count: 0 + OUTPUT message field count: 19 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -1(a) alias: -1(a) + : table: V_TEST owner: SYSDBA + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: +15 alias: +15 + : table: V_TEST owner: SYSDBA + 03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 32767 alias: 32767 + : table: V_TEST owner: SYSDBA + 04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 32768 alias: 32768 + : table: V_TEST owner: SYSDBA + 05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 65535 alias: 65535 + : table: V_TEST owner: SYSDBA + 06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 65536(a) alias: 65536(a) + : table: V_TEST owner: SYSDBA + 07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: 65536(b) alias: 65536(b) + : table: V_TEST owner: SYSDBA + 08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -2147483648 alias: -2147483648 + : table: V_TEST owner: SYSDBA + 09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +2147483648(a) alias: +2147483648(a) + : table: V_TEST owner: SYSDBA + 10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +2147483648(b) alias: +2147483648(b) + : table: V_TEST owner: SYSDBA + 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -1(b) alias: -1(b) + : table: V_TEST owner: SYSDBA + 12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967295 alias: +4294967295 + : table: V_TEST owner: SYSDBA + 13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967296(a) alias: +4294967296(a) + : table: V_TEST owner: SYSDBA + 14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967296(b) alias: +4294967296(b) + : table: V_TEST owner: SYSDBA + 15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: 9223372036854775807 alias: 9223372036854775807 + : table: V_TEST owner: SYSDBA + 16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775808 alias: -9223372036854775808 + : table: V_TEST owner: SYSDBA + 17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775807 alias: -9223372036854775807 + : table: V_TEST owner: SYSDBA + 18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775806 alias: -9223372036854775806 + : table: V_TEST owner: SYSDBA + 19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -1(c) alias: -1(c) + : table: V_TEST owner: SYSDBA + """ + else: + expected_sqlda = """ + INPUT message field count: 0 + OUTPUT message field count: 19 + 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -1(a) alias: -1(a) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: +15 alias: +15 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 32767 alias: 32767 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 32768 alias: 32768 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 65535 alias: 65535 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: 65536(a) alias: 65536(a) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: 65536(b) alias: 65536(b) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -2147483648 alias: -2147483648 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +2147483648(a) alias: +2147483648(a) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +2147483648(b) alias: +2147483648(b) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: -1(b) alias: -1(b) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967295 alias: +4294967295 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967296(a) alias: +4294967296(a) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: +4294967296(b) alias: +4294967296(b) + : table: V_TEST schema: PUBLIC owner: SYSDBA + 15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: 9223372036854775807 alias: 9223372036854775807 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775808 alias: -9223372036854775808 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775807 alias: -9223372036854775807 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -9223372036854775806 alias: -9223372036854775806 + : table: V_TEST schema: PUBLIC owner: SYSDBA + 19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: -1(c) alias: -1(c) + : table: V_TEST schema: PUBLIC owner: SYSDBA + """ + + expected_stdout = f""" + CONSTANT 11 + CONSTANT 0123456789 + CONSTANT 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + UUID_TO_CHAR BA1749B5-83BF-9146-B360-F54E25FE583E + -1(a) -1 + +15 15 + 32767 32767 + 32768 32768 + 65535 65535 + 65536(a) 65536 + 65536(b) 65536 + -2147483648 -2147483648 + +2147483648(a) 2147483648 + +2147483648(b) 2147483648 + -1(b) -1 + +4294967295 4294967295 + +4294967296(a) 4294967296 + +4294967296(b) 4294967296 + 9223372036854775807 9223372036854775807 + -9223372036854775808 -9223372036854775808 + -9223372036854775807 -9223372036854775807 + -9223372036854775806 -9223372036854775806 + -1(c) -1 + + {expected_sqlda} + """ + + expected_stderr = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 9 + -'1' + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Token unknown - line 1, column 9 + -'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x' + """ + act.expected_stdout = expected_stdout act.expected_stderr = expected_stderr act.execute() From 5e3c17f63c42cc41505d14d6c9a0f9cb74681adc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 00:39:14 +0300 Subject: [PATCH 0687/1064] Added/Updated tests\bugs\core_1793_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1793_test.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_1793_test.py b/tests/bugs/core_1793_test.py index 151dbfd8..a29221f0 100644 --- a/tests/bugs/core_1793_test.py +++ b/tests/bugs/core_1793_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1793 FBTEST: bugs.core_1793 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -24,26 +30,29 @@ set planonly; with x as (select x.x from test x), - y as (select y.x from test y) + y as (select y.x from test y), + z as (select x from test) select * from y; """ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ + SQL warning code = -104 + -CTE "X" is not used in query + -CTE "Z" is not used in query PLAN (Y Y NATURAL) """ -expected_stderr = """ +expected_stdout_6x = """ SQL warning code = -104 -CTE "X" is not used in query + -CTE "Z" is not used in query + PLAN ("Y" "Y" NATURAL) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 9373ff4b89cfa10ff168099f231831357eed89bc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 10:18:07 +0300 Subject: [PATCH 0688/1064] Added/Updated tests\bugs\core_1715_test.py: Increased max_version to 6.x. Checked on 6.0.0.876-6f6d168. --- tests/bugs/core_1715_test.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_1715_test.py b/tests/bugs/core_1715_test.py index 7a94e6cb..3e045be3 100644 --- a/tests/bugs/core_1715_test.py +++ b/tests/bugs/core_1715_test.py @@ -13,14 +13,10 @@ See: https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html#fblangref50-ddl-idx-limits ("Table 38. Maximum indexable (VAR)CHAR length") - Checked on 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. - - ::: NB ::: - FB 6.x: it seems that since '4fe307: Improvement #8406 - Increase MIN_PAGE_SIZE to 8192' we can NOT create DB with any size except 8192. - Sent report to Adriano, 26.06.2025 00:13. WAITING FOR REPLY. - - ### QA TODO. DEFERRED FOR FB 6.X ### + Bug existed on 6.x since '4fe307: Improvement #8406 - Increase MIN_PAGE_SIZE to 8192': only page_size = 8K was avaliable for usage. + Fixed in https://github.com/FirebirdSQL/firebird/commit/6f6d16831919c4fa279189f02b93346c4d5ac1bf + Checked on 6.0.0.876-6f6d168 ; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ from pathlib import Path import locale @@ -35,7 +31,7 @@ tmp_fdb = temp_file('tmp_core_1715.fdb') -@pytest.mark.version('>=3,<6') +@pytest.mark.version('>=3') def test_1(act: Action, tmp_fdb: Path, capsys): utf8_max_key_size_map = {4096 : (253, 169), 8192 : (509,339), 16384 : (1021,681)} From 8144e63d08aa0d1ffb85351c13dd5f4d322e23d2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 12:02:16 +0300 Subject: [PATCH 0689/1064] Added/Updated tests\bugs\core_1802_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1802_test.py | 96 +++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_1802_test.py b/tests/bugs/core_1802_test.py index e266ba36..57f26ed9 100644 --- a/tests/bugs/core_1802_test.py +++ b/tests/bugs/core_1802_test.py @@ -7,29 +7,103 @@ DESCRIPTION: JIRA: CORE-1802 FBTEST: bugs.core_1802 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db = db_factory() +db = db_factory(charset = 'win1250', page_size = 8192) + +test_script = """ + -- https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html#fblangref50-datatypes-chartypes-charindxs + -- The following formula calculates the maximum length of an indexed string (in characters): + -- max_char_length = FLOOR((page_size / 4 - 9) / N) + -- where N is the number of bytes per character in the character set. + create table test( + id int generated by default as identity + ,f01 varchar(999) character set win1250 collate pxw_csy + ); + create index test_f01_unq on test(f01); + commit; + + -- https://www.generatormix.com/random-czech-words-generator?number=50 + insert into test(f01) values('všechno'); + insert into test(f01) values('ženy'); + insert into test(f01) values('takové'); + insert into test(f01) values('vaši'); + insert into test(f01) values('velké'); + insert into test(f01) values('přijít'); + insert into test(f01) values('našeho'); + insert into test(f01) values('běžte'); + insert into test(f01) values('zatraceně'); + insert into test(f01) values('straně'); + insert into test(f01) values('bolí'); + insert into test(f01) values('svém'); + insert into test(f01) values('místa'); + insert into test(f01) values('mrzí'); + insert into test(f01) values('příště'); + insert into test(f01) values('horší'); + insert into test(f01) values('mladý'); + insert into test(f01) values('dívka'); + insert into test(f01) values('lásku'); + insert into test(f01) values('cítit'); + insert into test(f01) values('nedá'); + insert into test(f01) values('rozhodnutí'); + insert into test(f01) values('dětí'); + insert into test(f01) values('náma'); + insert into test(f01) values('těžký'); + insert into test(f01) values('líbilo'); + insert into test(f01) values('píše'); + insert into test(f01) values('dívku'); + insert into test(f01) values('zbývá'); + insert into test(f01) values('dítě'); + insert into test(f01) values('haló'); + insert into test(f01) values('děkuju'); + insert into test(f01) values('jaké'); + insert into test(f01) values('potřebuji'); + insert into test(f01) values('půl'); + insert into test(f01) values('skutečně'); + insert into test(f01) values('chtěli'); + insert into test(f01) values('okamžitě'); + insert into test(f01) values('slyšela'); + insert into test(f01) values('krásná'); + insert into test(f01) values('mrzí'); + insert into test(f01) values('zapomeň'); + insert into test(f01) values('lásku'); + insert into test(f01) values('dávej'); + insert into test(f01) values('museli'); + insert into test(f01) values('zachránil'); + insert into test(f01) values('každej'); + insert into test(f01) values('milé'); + insert into test(f01) values('neznamená'); + insert into test(f01) values('polož'); + insert into test(f01) values('zbraní'); + insert into test(f01) values('tátu'); + insert into test(f01) values('několika'); + commit; -test_script = """CREATE TABLE TAB21( - ID INTEGER, - A VARCHAR(490) CHARACTER SET WIN1250 COLLATE PXW_CSY, - CONSTRAINT CU UNIQUE(A) ); -COMMIT; -SHOW INDEX CU; + set planonly; + select * from test where f01 = 'náma'; """ act = isql_act('db', test_script) -expected_stdout = """CU UNIQUE INDEX ON TAB21(A) +expected_stdout_5x = """ + PLAN (TEST INDEX (TEST_F01_UNQ)) +""" + +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01_UNQ")) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], charset = 'win1250', input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From c24d883de2d93d5a0937871a7704b158d3ba950b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 12:07:54 +0300 Subject: [PATCH 0690/1064] Added/Updated tests\bugs\core_1812_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1812_test.py | 64 ++++++++++-------------------------- 1 file changed, 17 insertions(+), 47 deletions(-) diff --git a/tests/bugs/core_1812_test.py b/tests/bugs/core_1812_test.py index 2c7cb5ed..9f25ec92 100644 --- a/tests/bugs/core_1812_test.py +++ b/tests/bugs/core_1812_test.py @@ -8,53 +8,19 @@ JIRA: CORE-1812 FBTEST: bugs.core_1812 NOTES: - [02.02.2019] pzotov - Added separate code for FB 4.0: statements like "SELECT TIMESTAMP 'now' FROM RDB$DATABASE;" can not - be used anymore (error: SQLSTATE = 22018 / conversion error from string "now"). - Details about timezone datatype see in: doc\\sql.extensions\\README.time_zone.md + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. - [01.09.2023] pzotov - Adjusted plan for FB 4.x+ to current versions after fixed - https://github.com/FirebirdSQL/firebird/issues/7727 + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -# version: 3.0 +db = db_factory(sql_dialect=1) -init_script_1 = """ - create table t (col timestamp) ; - create index it on t (col) ; - commit ; - """ - -db_1 = db_factory(sql_dialect=1, init=init_script_1) - -test_script_1 = """ - SET PLAN ON; - select * from t where col > timestamp 'now' - 7 ; - select * from t where col > 'now' - 7 ; -""" - -act_1 = isql_act('db_1', test_script_1) - -expected_stdout_1 = """ - PLAN (T INDEX (IT)) - PLAN (T INDEX (IT)) -""" - -@pytest.mark.version('>=3.0,<4.0') -def test_1(act_1: Action): - act_1.expected_stdout = expected_stdout_1 - act_1.execute() - assert act_1.clean_stdout == act_1.clean_expected_stdout - -# version: 4.0 - -db_2 = db_factory(sql_dialect=1) - -test_script_2 = """ +test_script = """ create table test (dts timestamp) ; commit; insert into test @@ -69,16 +35,20 @@ def test_1(act_1: Action): select * from test where dts = current_timestamp; """ -act_2 = isql_act('db_2', test_script_2) +act = isql_act('db', test_script) -expected_stdout_2 = """ +expected_stdout_5x = """ PLAN (TEST INDEX (TEST_DTS)) PLAN (TEST INDEX (TEST_DTS)) """ -@pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stdout = expected_stdout_2 - act_2.execute() - assert act_2.clean_stdout == act_2.clean_expected_stdout +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_DTS")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_DTS")) +""" +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 92e502c504db7eb66d837422b3a0ea96681506c3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 12:57:44 +0300 Subject: [PATCH 0691/1064] Added/Updated tests\bugs\core_1815_test.py: Re-implemented: use fixture attributes and f-notation instead of hard-coding user/role names. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_1815_test.py | 811 ++++++++++++++++++++--------------- 1 file changed, 459 insertions(+), 352 deletions(-) diff --git a/tests/bugs/core_1815_test.py b/tests/bugs/core_1815_test.py index 7486c2a0..494fb594 100644 --- a/tests/bugs/core_1815_test.py +++ b/tests/bugs/core_1815_test.py @@ -5,402 +5,509 @@ ISSUE: 2245 TITLE: Ability to grant role to another role DESCRIPTION: - ### NB ### This test was NOT completed! - One need to check all nuances related to granting and revoking that is issued by NON sysdba user - which was granted admin option to manupulate appropriate DB objects. - Also, there is not clarity about issue 08/Aug/16 06:31 AM (when user Boss2 does grant-and-revoke - sequence with some role to other user Sales but this role already was granted by _other_ user, Boss1). - - We create two users (acnt and pdsk) and two roles for them (racnt and rpdsk). - Then we create two tables (tacnt & tpdsk) and grant access on these tables for acnt & pdsk. - Then we create user boss, role for him (rboss) and grant IMPLICITLY access on tables tacnt and tpdsk - to user boss via his role (rboss). - Check is made to ensure that user boss HAS ability to read from both tables (being connected with role Rboss). - After all, we IMPLICITLY revoke access from these tables and check again that user boss now has NO access - on tables tacnt and tpdsk. + ### NB ### This test was NOT completed! + One need to check all nuances related to granting and revoking that is issued by NON sysdba user + which was granted admin option to manupulate appropriate DB objects. + Also, there is not clarity about issue 08/Aug/16 06:31 AM (when user Boss2 does grant-and-revoke + sequence with some role to other user Sales but this role already was granted by _other_ user, Boss1). + + We create two users (acnt and pdsk) and two roles for them (racnt and rpdsk). + Then we create two tables (tacnt & tpdsk) and grant access on these tables for acnt & pdsk. + Then we create user boss, role for him (rboss) and grant IMPLICITLY access on tables tacnt and tpdsk + to user boss via his role (rboss). + Check is made to ensure that user boss HAS ability to read from both tables (being connected with role Rboss). + After all, we IMPLICITLY revoke access from these tables (by revoking ROLES from boss) and check again that + user boss now has NO access on tables tacnt and tpdsk. JIRA: CORE-1815 FBTEST: bugs.core_1815 +NOTES: + [26.06.2025] pzotov + Re-implemented: use fixture attributes and f-notation instead of hard-coding user/role names. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest from firebird.qa import * db = db_factory() + user_boss = user_factory('db', name='tmp$c1815_boss', password='boss') user_acnt = user_factory('db', name='tmp$c1815_acnt', password='acnt') user_pdsk = user_factory('db', name='tmp$c1815_pdsk', password='pdsk') -test_script = """ - set wng off; - --show version; - --set bail on; - --set echo on; - set list on; - - set width whoami 16; - set width my_role 7; - set width r_name 10; - set width r_owner 10; - - create or alter view v_role_info as - select - current_user as whoami, - current_role as my_role, - rdb$role_name as r_name, - rdb$owner_name r_owner, - rdb$role_in_use(rdb$role_name) r_in_use - from rdb$roles - where coalesce(rdb$system_flag,0) = 0 - ; - commit; - - create role rboss; - create role racnt; - create role rpdsk; - commit; - - grant select on v_role_info to user tmp$c1815_acnt; - grant select on v_role_info to user tmp$c1815_pdsk; - grant select on v_role_info to user tmp$c1815_boss; - commit; - - grant racnt to user tmp$c1815_acnt; - grant rpdsk to user tmp$c1815_pdsk; - commit; - - ------------------------------------------------------------------------ - - recreate table tacnt(id int, s varchar(5)); - recreate table tpdsk(id int, s varchar(5)); - commit; - - grant all on tacnt to role racnt; - grant all on tpdsk to role rpdsk; - commit; - - ------------------------------------------------------------------------ - - grant racnt to rboss; -- make RBOSS role able to do the same as role RACNT - grant rpdsk to rboss; -- make RBOSS role able to do the same as role RPDSK - - grant rboss to tmp$c1815_boss; -- let user BOSS to use role RBOSS - - commit; - --show grants; -- [ 1 ] - - ------------------------------------------------------------------------ - - insert into tacnt(id, s) values(1,'acnt'); - insert into tpdsk(id, s) values(2,'pdsk'); - commit; - - connect '$(DSN)' user tmp$c1815_acnt password 'acnt' role 'racnt'; - select * from v_role_info; - select current_user as whoami, a.* from tacnt a; - commit; - - connect '$(DSN)' user tmp$c1815_pdsk password 'pdsk' role 'rpdsk'; - select * from v_role_info; - select current_user as whoami, p.* from tpdsk p; - commit; - - - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; - select * from v_role_info; - commit; - - select current_user as whoami, a.* from tacnt a; - select current_user as whoami, p.* from tpdsk p; - commit; - - --################################################################################################ - - connect '$(DSN)' user sysdba password 'masterkey'; - - revoke racnt from user tmp$c1815_acnt; -- REVOKE role from *other* USER; grant to RBoss should be reserved! - commit; +role_boss = role_factory('db', name='role_boss') +role_acnt = role_factory('db', name='role_acnt') +role_pdsk = role_factory('db', name='role_pdsk') - -- check that *role* RBoss still HAS grants to both RAcnt and RPdsk roles: - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; - select * from v_role_info; -- should contain in all three rows +substitutions = [] # [('[ \t]+', ' ')] +act = isql_act('db', substitutions = substitutions) - -- should PASS because we revoked role from other USER (accountant) - -- rather than from current user (Boss) or its role (Rboss): - select current_user as whoami, a.* from tacnt a; - commit; - - --#################################################################################################### - - connect '$(DSN)' user sysdba password 'masterkey'; - - -- check that if we try to revoke role RPdsk from __USER__ Boss than - -- this action will not has effect because this USER got access through the ROLE (i.e. indirectly): - - revoke rpdsk from user tmp$c1815_boss; -- this is no-op action! We did NOT granted role to USER! - commit; - - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; -- now check: is role Rboss really affected ? - - select * from v_role_info; -- should contain in all lines because we did not affect __role__ RBOSS - select current_user as whoami, p.* from tpdsk p; -- should PASS! - commit; - - --################################################################################################ - - connect '$(DSN)' user sysdba password 'masterkey'; - - -- check that if we revoke access to a table from ROLE RPdsk (and this role was granted to role RBoss) - -- then Rboss also will not be able to select from this table: - - revoke all on tpdsk from rpdsk; - commit; - - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; - - select * from v_role_info; -- should contain in all lines because we did not affect __role__ RBOSS - select current_user as whoami, p.* from tpdsk p; -- should FAIL - commit; - - --################################################################################################ - - connect '$(DSN)' user sysdba password 'masterkey'; - - -- check that if we revoke ROLE 'racnt' which was granted before to ROLE 'rboss' - -- then user Boss will not be able to access table 'tacnt' (i.e. we revoke this access indirectly): - - revoke racnt from rboss; - commit; - - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; - - select * from v_role_info; -- should contain for line with 'racnt' - select current_user as whoami, a.* from tacnt a; -- should FAIL - commit; +@pytest.mark.version('>=4.0') +def test_1(act: Action, user_boss: User, user_acnt: User, user_pdsk: User, role_boss: Role, role_acnt: Role, role_pdsk: Role): - -- ############################################################################################### + test_script = f""" + set wng off; + set list on; - connect '$(DSN)' user sysdba password 'masterkey'; + set width whoami 16; + set width my_role 7; + set width r_name 10; + set width r_owner 10; - -- check that if we GRANT again ROLE 'racnt' which was revoked before from ROLE 'rboss' - -- then user Boss WILL be able to access table 'tacnt' (we grant access indirectly after revoking): + create or alter view v_role_info as + select + current_user as whoami, + current_role as my_role, + rdb$role_name as r_name, + rdb$owner_name r_owner, + rdb$role_in_use(rdb$role_name) r_in_use + from rdb$roles + where coalesce(rdb$system_flag,0) = 0 + ; + commit; - grant racnt to rboss; -- RESTORE access for role Rboss - commit; + grant select on v_role_info to user {user_acnt.name}; + grant select on v_role_info to user {user_pdsk.name}; + grant select on v_role_info to user {user_boss.name}; + commit; + grant {role_acnt.name} to user {user_acnt.name}; + grant {role_pdsk.name} to user {user_pdsk.name}; + commit; - connect '$(DSN)' user tmp$c1815_boss password 'boss' role 'rboss'; + ------------------------------------------------------------------------ - select * from v_role_info; -- should contain for line with 'racnt' - select current_user as whoami, a.* from tacnt a; -- should PASS - commit; -""" + recreate table tacnt(id int, s varchar(15)); + recreate table tpdsk(id int, s varchar(15)); + commit; -act = isql_act('db', test_script) + grant all on tacnt to role {role_acnt.name}; + grant all on tpdsk to role {role_pdsk.name}; + commit; -expected_stdout = """ - WHOAMI TMP$C1815_ACNT - MY_ROLE RACNT - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE + ------------------------------------------------------------------------ - WHOAMI TMP$C1815_ACNT - MY_ROLE RACNT - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE + grant {role_acnt.name} to {role_boss.name}; -- make {role_boss.name} role able to do the same as role {role_acnt.name} + grant {role_pdsk.name} to {role_boss.name}; -- make {role_boss.name} role able to do the same as role {role_pdsk.name} - WHOAMI TMP$C1815_ACNT - MY_ROLE RACNT - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE + grant {role_boss.name} to {user_boss.name}; -- let user BOSS to use role {role_boss.name} + commit; + --show grants; -- [ 1 ] - WHOAMI TMP$C1815_ACNT - ID 1 - S acnt + ------------------------------------------------------------------------ + insert into tacnt(id, s) values(1, '{role_acnt.name.upper()}'); + insert into tpdsk(id, s) values(2, '{role_pdsk.name.upper()}'); + commit; - WHOAMI TMP$C1815_PDSK - MY_ROLE RPDSK - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE + connect '{act.db.dsn}' user {user_acnt.name} password '{user_acnt.password}' role '{role_acnt.name}'; + select * from v_role_info; + select current_user as whoami, a.* from tacnt a; + commit; - WHOAMI TMP$C1815_PDSK - MY_ROLE RPDSK - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE + connect '{act.db.dsn}' user {user_pdsk.name} password '{user_pdsk.password}' role '{role_pdsk.name}'; + select * from v_role_info; + select current_user as whoami, p.* from tpdsk p; + commit; - WHOAMI TMP$C1815_PDSK - MY_ROLE RPDSK - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; + select * from v_role_info; + commit; - WHOAMI TMP$C1815_PDSK - ID 2 - S pdsk + select current_user as whoami, a.* from tacnt a; + select current_user as whoami, p.* from tpdsk p; + commit; + --################################################################################################ - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE - - - WHOAMI TMP$C1815_BOSS - ID 1 - S acnt - - WHOAMI TMP$C1815_BOSS - ID 2 - S pdsk - - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE - - - WHOAMI TMP$C1815_BOSS - ID 1 - S acnt - - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE + revoke {role_acnt.name} from user {user_acnt.name}; -- REVOKE role from *other* USER; grant to {role_boss.name} should be preserved! + commit; + -- check that *role* {role_boss.name} still HAS grants to both {role_acnt.name} and {role_pdsk.name} roles: + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; - WHOAMI TMP$C1815_BOSS - ID 2 - S pdsk + select * from v_role_info; -- should contain in all three rows + -- should PASS because we revoked role from other USER (accountant) + -- rather than from current user (Boss) or its role ({role_boss.name}): + select current_user as whoami, a.* from tacnt a; + commit; - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE + --#################################################################################################### + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE - - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RBOSS - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RACNT - R_OWNER SYSDBA - R_IN_USE - - WHOAMI TMP$C1815_BOSS - MY_ROLE RBOSS - R_NAME RPDSK - R_OWNER SYSDBA - R_IN_USE - - - - WHOAMI TMP$C1815_BOSS - ID 1 - S acnt -""" + -- check that if we try to revoke role {role_pdsk.name} from __USER__ Boss than + -- this action will not has effect because this USER got access through the ROLE (i.e. indirectly): -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TPDSK - -Effective user is TMP$C1815_BOSS + revoke {role_pdsk.name} from user {user_boss.name}; -- this is no-op action: we did NOT granted role to USER. + commit; - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TACNT - -Effective user is TMP$C1815_BOSS -""" + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; -- now check: is role {role_boss.name} really affected ? -@pytest.mark.version('>=4.0') -def test_1(act: Action, user_boss: User, user_acnt: User, user_pdsk: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + select * from v_role_info; -- should contain in all lines because we did not affect __role__ {role_boss.name} + select current_user as whoami, p.* from tpdsk p; -- should PASS! + commit; + --################################################################################################ + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + + -- check that if we revoke access to a table from ROLE {role_pdsk.name} (and this role was granted to role {role_boss.name}) + -- then {role_boss.name} also will not be able to select from this table: + + revoke all on tpdsk from {role_pdsk.name}; + commit; + + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; + + select * from v_role_info; -- should contain in all lines because we did not affect __role__ {role_boss.name} + select current_user as whoami, p.* from tpdsk p; -- should FAIL + commit; + + --################################################################################################ + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + + -- check that if we revoke ROLE '{role_acnt.name}' which was granted before to ROLE '{role_boss.name}' + -- then user Boss will not be able to access table 'tacnt' (i.e. we revoke this access indirectly): + + revoke {role_acnt.name} from {role_boss.name}; + commit; + + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; + + select * from v_role_info; -- should contain for line with '{role_acnt.name}' + select current_user as whoami, a.* from tacnt a; -- should FAIL + commit; + + -- ############################################################################################### + + connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; + + -- check that if we GRANT again ROLE '{role_acnt.name}' which was revoked before from ROLE '{role_boss.name}' + -- then user Boss WILL be able to access table 'tacnt' (we grant access indirectly after revoking): + + grant {role_acnt.name} to {role_boss.name}; -- RESTORE access for role {role_boss.name} + commit; + + + connect '{act.db.dsn}' user {user_boss.name} password '{user_boss.password}' role '{role_boss.name}'; + + select * from v_role_info; -- should contain for line with '{role_acnt.name}' + select current_user as whoami, a.* from tacnt a; -- should PASS + commit; + """ + + + expected_stdout_5x = f""" + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_boss.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TPDSK + -Effective user is {user_boss.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TACNT + -Effective user is {user_boss.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + """ + + expected_stdout_6x = f""" + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + MY_ROLE {role_acnt.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_acnt.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + MY_ROLE {role_pdsk.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_pdsk.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_boss.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 2 + S {role_pdsk.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE "PUBLIC"."TPDSK" + -Effective user is {user_boss.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE "PUBLIC"."TACNT" + -Effective user is {user_boss.name.upper()} + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_boss.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_acnt.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + MY_ROLE {role_boss.name.upper()} + R_NAME {role_pdsk.name.upper()} + R_OWNER {act.db.user.upper()} + R_IN_USE + WHOAMI {user_boss.name.upper()} + ID 1 + S {role_acnt.name.upper()} + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 56cc0f80720cd4137283b03e9897bdceea5de681 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:10:32 +0300 Subject: [PATCH 0692/1064] Added/Updated tests\bugs\core_1830_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1830_test.py | 100 +++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/tests/bugs/core_1830_test.py b/tests/bugs/core_1830_test.py index 9ea2765b..beb2d712 100644 --- a/tests/bugs/core_1830_test.py +++ b/tests/bugs/core_1830_test.py @@ -7,25 +7,29 @@ DESCRIPTION: JIRA: CORE-1830 FBTEST: bugs.core_1830 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ create table a(id char(1), name varchar(255)); create index idx_a on a (id); - create exception ex_perm 'Something wrong occurs...'; + create exception exc_wrong 'Something wrong occurs...'; commit ; insert into a (id) values ('1'); commit; -""" -db = db_factory(init=init_script) - -test_script = """ set list on; select * from a where id = '1'; set term ^; @@ -33,46 +37,64 @@ begin update a set name = 'xxx'; update a set id = '2'; - exception ex_perm; + exception exc_wrong; end ^ set term ; ^ - select * from a ; - select * from a where id = '1' ; - + set count on; + select 'point-1' as msg, a.* from a ; + select 'point-2' as msg, a.* from a where id = '1' ; commit; - select * from a ; + select 'point-3' as msg, a.* from a ; """ -act = isql_act('db', test_script, - substitutions=[('column.*', 'column x'), ('[ \t]+', ' '), - ('-At block line: [\\d]+, col: [\\d]+', '')]) - -expected_stdout = """ - ID 1 - NAME - - ID 1 - NAME - - ID 1 - NAME - - ID 1 - NAME +substitutions = [ ('[ \t]+', ' '), ('column.*', 'column x'), ('-At block line: [\\d]+, col: [\\d]+', '')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + ID 1 + NAME + Statement failed, SQLSTATE = HY000 + exception 1 + -EXC_WRONG + -Something wrong occurs... + MSG point-1 + ID 1 + NAME + Records affected: 1 + + MSG point-2 + ID 1 + NAME + Records affected: 1 + + MSG point-3 + ID 1 + NAME + Records affected: 1 """ - -expected_stderr = """ - Statement failed, SQLSTATE = HY000 - exception 1 - -EX_PERM - -Something wrong occurs... +expected_stdout_6x = """ + ID 1 + NAME + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EXC_WRONG" + -Something wrong occurs... + MSG point-1 + ID 1 + NAME + Records affected: 1 + MSG point-2 + ID 1 + NAME + Records affected: 1 + MSG point-3 + ID 1 + NAME + Records affected: 1 """ @pytest.mark.version('>=2.5') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 9208092c70ae1e9b10b70a66fedd380bec663de7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:20:11 +0300 Subject: [PATCH 0693/1064] Added/Updated tests\bugs\core_1841_test.py: Re-implemented: use f-notation in order to remove hard-coded DDL string from test_script and expected_out. Removed 'SHOW VIEW'command because its output can change in any intensive developing FB version. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1841_test.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_1841_test.py b/tests/bugs/core_1841_test.py index ce683d05..cbe9ed7a 100644 --- a/tests/bugs/core_1841_test.py +++ b/tests/bugs/core_1841_test.py @@ -5,10 +5,14 @@ ISSUE: 2270 TITLE: Possible overflow in RDB$VIEW_RELATIONS.RDB$CONTEXT_NAME DESCRIPTION: - Originale tite is: If some VIEW used derived tables and long table names/aliases, - It is possible to overflow RDB$VIEW_RELATIONS.RDB$CONTEXT_NAME + Original titte is: If some VIEW used derived tables and long table names/aliases, it is possible to overflow RDB$VIEW_RELATIONS.RDB$CONTEXT_NAME JIRA: CORE-1841 FBTEST: bugs.core_1841 +NOTES: + [26.06.2025] pzotov + Re-implemented: use f-notation in order to remove hard-coded DDL string from test_script and expected_out. + Removed 'SHOW VIEW'command because its output can change in any intensive developing FB version. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,26 +20,28 @@ db = db_factory() -test_script = """create view x (id) as -select RDB$RELATION_ID - from (select * from RDB$DATABASE long_alias_long_alias_1) long_alias_long_alias_2; -COMMIT; -SHOW VIEW x; +VIEW_DDL = 'select rdb$relation_id from (select * from rdb$database long_alias_long_alias_1) long_alias_long_alias_2' +test_script = f""" + set list on; + set blob all; + set count on; + create view v_test (id) as + {VIEW_DDL}; + commit; + select r.rdb$view_source as blob_id from rdb$relations r where r.rdb$relation_name = upper('v_test'); """ -act = isql_act('db', test_script) +substitutions = [('BLOB_ID .*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ID SMALLINT Expression -View Source: -==== ====== - -select RDB$RELATION_ID - from (select * from RDB$DATABASE long_alias_long_alias_1) long_alias_long_alias_2 +expected_stdout = f""" + {VIEW_DDL} + Records affected: 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 358b4059f894269c1ad97edf6b8fc43fb9bc88c1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:22:37 +0300 Subject: [PATCH 0694/1064] Added/Updated tests\bugs\core_1846_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1846_test.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_1846_test.py b/tests/bugs/core_1846_test.py index 47feb3f4..99ce92ef 100644 --- a/tests/bugs/core_1846_test.py +++ b/tests/bugs/core_1846_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-1846 FBTEST: bugs.core_1846 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -36,14 +42,18 @@ act = isql_act('db', test_script, substitutions=[('=.*', '')]) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST ORDER TEST_N1_N2_ASC) PLAN (TEST ORDER TEST_N2_N1_DESC) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_N1_N2_ASC") + PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_N2_N1_DESC") +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 5b63027899ef1fb0956f4f9ac4e85f82f49ecefb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:27:15 +0300 Subject: [PATCH 0695/1064] Added/Updated tests\bugs\core_1891_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1891_test.py | 43 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_1891_test.py b/tests/bugs/core_1891_test.py index 759d320e..9a92d0f1 100644 --- a/tests/bugs/core_1891_test.py +++ b/tests/bugs/core_1891_test.py @@ -7,32 +7,47 @@ DESCRIPTION: JIRA: CORE-1891 FBTEST: bugs.core_1891 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table test (n integer); -create view view_test (x, y) as select n, n * 2 from test; +db = db_factory() + +VIEW_DDL = 'select n, n * 2 from test' +test_script = f""" + create table test (n integer); + create view view_test (x, y) as + {VIEW_DDL}; + show view view_test; """ -db = db_factory(init=init_script) +substitutions = [ ('[ \t]+', ' '), ('=.*', '') ] +act = isql_act('db', test_script, substitutions = substitutions) -test_script = """show view view_test; +expected_stdout_5x = f""" + X INTEGER Nullable + Y BIGINT Expression + View Source: + {VIEW_DDL} """ -act = isql_act('db', test_script) - -expected_stdout = """X INTEGER Nullable -Y BIGINT Expression -View Source: -==== ====== - select n, n * 2 from test +expected_stdout_6x = f""" + View: PUBLIC.VIEW_TEST + X INTEGER Nullable + Y BIGINT Expression + View Source: + {VIEW_DDL} """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 8a496c3b2f315e4e0b9c92b77194e2e3b79b3ebd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:30:31 +0300 Subject: [PATCH 0696/1064] Added/Updated tests\bugs\core_1894_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1894_test.py | 38 +++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_1894_test.py b/tests/bugs/core_1894_test.py index 6589cbba..46726198 100644 --- a/tests/bugs/core_1894_test.py +++ b/tests/bugs/core_1894_test.py @@ -3,10 +3,16 @@ """ ID: issue-2325 ISSUE: 2325 -TITLE: Circular dependencies between computed fields crashs the engine +TITLE: Circular dependencies between computed fields crash the engine DESCRIPTION: JIRA: CORE-1894 FBTEST: bugs.core_1894 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -37,12 +43,11 @@ select * from t; select * from t2; -- THIS LEAD SERVER CRASH (checked on WI-T4.0.0.399) - """ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -Cannot have circular dependencies with computed fields @@ -63,9 +68,28 @@ -there are 1 dependencies """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -Cannot have circular dependencies with computed fields + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."T2"."C1" + -there are 1 dependencies + + Statement failed, SQLSTATE = 42000 + Cannot have circular dependencies with computed fields + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."T2"."C1" + -there are 1 dependencies +""" + @pytest.mark.version('>=3.0.2') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4aff7dc575127bfecd39d514b6bf33a9534a5326 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:38:02 +0300 Subject: [PATCH 0697/1064] Added/Updated tests\bugs\core_1930_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_1930_test.py | 167 ++++++++--------------------------- 1 file changed, 35 insertions(+), 132 deletions(-) diff --git a/tests/bugs/core_1930_test.py b/tests/bugs/core_1930_test.py index 49bb081c..dc7f4610 100644 --- a/tests/bugs/core_1930_test.py +++ b/tests/bugs/core_1930_test.py @@ -7,122 +7,25 @@ DESCRIPTION: JIRA: CORE-1930 FBTEST: bugs.core_1930 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest from firebird.qa import * -substitutions = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), - ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] +substitutions = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] db = db_factory() -# version: 3.0 - -test_script_1 = """ - set term ^; - create or alter procedure sp1 returns (x int) as - begin - x=1; - suspend; - end - ^ - - create or alter procedure sp2 returns (x int) as - begin - select x from sp1 into :x; - suspend; - end - ^ - - create or alter procedure sp3 returns (x int) as - begin - select x from sp2 into :x; - suspend; - end - ^ - commit - ^ - - -- this is wrong but engine still didn't track procedure's fields dependencies - create or alter procedure sp1 as - begin - exit; - end - ^ - - set term ;^ - commit; - - -- Here we create new attachment using specification of some non-null data in ROLE clause: - set term ^; - execute block as - declare c int; - begin - begin - c = rdb$get_context('SYSTEM', 'EXT_CONN_POOL_SIZE'); - rdb$set_context('USER_SESSION', 'EXT_CONN_POOL_SUPPORT','1'); - when any do - begin - end - end - execute statement 'create or alter procedure sp3 as begin execute procedure sp2; end' - on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') - as user 'sysdba' password 'masterkey' role 'R1930'; - end - ^ - commit - ^ - - -- |||||||||||||||||||||||||||| - -- ###################################||| HQBird 3.x SS/SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (avaliable in HQbird 3.x) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - execute block as - begin - if ( rdb$get_context('USER_SESSION', 'EXT_CONN_POOL_SUPPORT') = '1' ) then - begin - -- HQbird is tested now: - -- execute statement 'delete from mon$attachments where mon$attachment_id != current_connection'; - execute statement 'ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL'; - end - end - ^ - commit - ^ -""" - -act_1 = isql_act('db', test_script_1, substitutions=substitutions) - -expected_stderr_1 = """ - Statement failed, SQLSTATE = 42000 - Execute statement error at isc_dsql_execute2 : - 335544351 : unsuccessful metadata update - 336397267 : CREATE OR ALTER PROCEDURE SP3 failed - 335544569 : Dynamic SQL Error - 335544850 : Output parameter mismatch for procedure SP2 - Statement : create or alter procedure sp3 as begin execute procedure sp2; end - Data source : Firebird::localhost:C:\\MIX\\FIREBIRD\\QA\\FBT-REPO\\TMP\\C1930.FDB - -At block line: 3, col: 9 -""" - -@pytest.mark.version('>=3.0,<4.0') -def test_1(act_1: Action): - act_1.expected_stderr = expected_stderr_1 - act_1.execute() - assert act_1.clean_stderr == act_1.clean_expected_stderr - -# version: 4.0 +# Statement that will be passed in ES/EDS (we have to check its presence in error message): +EDS_STATEMENT = 'create or alter procedure sp3 as begin execute procedure sp2; end' -test_script_2 = """ +test_script = f""" set term ^; create or alter procedure sp1 returns (x int) as begin @@ -164,34 +67,18 @@ def test_1(act_1: Action): set term ^; execute block as begin - execute statement 'create or alter procedure sp3 as begin execute procedure sp2; end' + execute statement '{EDS_STATEMENT}' on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') as user 'sysdba' password 'masterkey' role 'R1930'; end ^ set term ;^ commit; - - -- |||||||||||||||||||||||||||| - -- ###################################||| FB 4.0+, SS and SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - - delete from mon$attachments where mon$attachment_id != current_connection; - commit; """ -act_2 = isql_act('db', test_script_2, substitutions=substitutions) +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr_2 = """ +expected_stdout_5x = f""" Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete @@ -204,15 +91,31 @@ def test_1(act_1: Action): 336397267 : CREATE OR ALTER PROCEDURE SP3 failed 335544569 : Dynamic SQL Error 335544850 : Output parameter mismatch for procedure SP2 - Statement : create or alter procedure sp3 as begin execute procedure sp2; end + Statement : {EDS_STATEMENT} + Data source : Firebird::localhost: + -At block line +""" + +expected_stdout_6x = f""" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -PARAMETER "PUBLIC"."SP1".X + -there are 1 dependencies + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_execute2 : + 335544351 : unsuccessful metadata update + 336397267 : CREATE OR ALTER PROCEDURE "PUBLIC"."SP3" failed + 335544569 : Dynamic SQL Error + 335544850 : Output parameter mismatch for procedure "PUBLIC"."SP2" + Statement : {EDS_STATEMENT} Data source : Firebird::localhost: -At block line """ @pytest.mark.es_eds @pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert act_2.clean_stderr == act_2.clean_expected_stderr - +def test_2(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From cffb5b6569f5b521f884c0263c0cfba19ad56da8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 13:56:28 +0300 Subject: [PATCH 0698/1064] Added/Updated tests\bugs\core_1986_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_1986_test.py | 63 ++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/tests/bugs/core_1986_test.py b/tests/bugs/core_1986_test.py index 34430a30..74564e19 100644 --- a/tests/bugs/core_1986_test.py +++ b/tests/bugs/core_1986_test.py @@ -7,42 +7,55 @@ DESCRIPTION: JIRA: CORE-1986 FBTEST: bugs.core_1986 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest from firebird.qa import * -init_script = """CREATE DOMAIN D_SOME AS INTEGER; - -CREATE OR ALTER PROCEDURE SP_SOME( - SOME_PARAM D_SOME) -AS -BEGIN -END; +db = db_factory() + +test_script = """ + create domain dm_int as int; + set term ^; + create or alter procedure sp_some(a_x dm_int) + as + begin + end + ^ + set term ;^ + alter domain dm_int to d_other; + execute procedure sp_some (1); + commit; + execute procedure sp_some (1); + commit; """ -db = db_factory(init=init_script) - -test_script = """ALTER DOMAIN D_SOME TO D_OTHER; +act = isql_act('db', test_script) -execute procedure SP_SOME (1); -commit; -execute procedure SP_SOME (1); -commit; +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -DOMAIN DM_INT + -there are 1 dependencies """ -act = isql_act('db', test_script) - -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --DOMAIN D_SOME --there are 1 dependencies +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -DOMAIN "PUBLIC"."DM_INT" + -there are 1 dependencies """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From b337ba39af59eed720241ebd8b8d56d3ec62704d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 14:01:26 +0300 Subject: [PATCH 0699/1064] Added/Updated tests\bugs\core_1997_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1997_test.py | 66 +++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/tests/bugs/core_1997_test.py b/tests/bugs/core_1997_test.py index 9845f0df..acd764f6 100644 --- a/tests/bugs/core_1997_test.py +++ b/tests/bugs/core_1997_test.py @@ -3,48 +3,58 @@ """ ID: issue-2434 ISSUE: 2434 -TITLE: Broken foreign key handling for multi-segmented index using multi-level collations +TITLE: Broken foreign key handling for multi-segmented index using unicode_ci collation DESCRIPTION: JIRA: CORE-1997 FBTEST: bugs.core_1997 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table pk ( - c1 varchar (5) character set utf8 collate unicode_ci, - c2 varchar (5) character set utf8 collate unicode_ci, - primary key (c1, c2) -); -commit; -create table fk ( - c1 varchar (5) character set utf8 collate unicode_ci, - c2 varchar (5) character set utf8 collate unicode_ci, - foreign key (c1, c2) references pk -); -commit; -insert into pk values ('a', 'b'); -insert into fk values ('A', 'b'); -commit; +db = db_factory() + +test_script = """ + create table pk ( + c1 varchar (5) character set utf8 collate unicode_ci, + c2 varchar (5) character set utf8 collate unicode_ci, + primary key (c1, c2) + ); + create table fk ( + c1 varchar (5) character set utf8 collate unicode_ci, + c2 varchar (5) character set utf8 collate unicode_ci, + foreign key (c1, c2) references pk + ); + insert into pk values ('a', 'b'); + insert into fk values ('A', 'b'); + commit; + delete from pk; -- should not be allowed """ -db = db_factory(init=init_script) +act = isql_act('db', test_script) -test_script = """delete from pk; -- should not be allowed +expected_stdout_5x = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "INTEG_2" on table "FK" + -Foreign key references are present for the record + -Problematic key value is ("C1" = 'a', "C2" = 'b') """ -act = isql_act('db', test_script) - -expected_stderr = """Statement failed, SQLSTATE = 23000 -violation of FOREIGN KEY constraint "INTEG_2" on table "FK" --Foreign key references are present for the record --Problematic key value is ("C1" = 'a', "C2" = 'b') +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "INTEG_2" on table "PUBLIC"."FK" + -Foreign key references are present for the record + -Problematic key value is ("C1" = 'a', "C2" = 'b') """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 120abc1070e05c56bdd7ece9f29600fc3bb756ef Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 15:37:34 +0300 Subject: [PATCH 0700/1064] Added/Updated tests\bugs\core_2053_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2053_test.py | 52 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_2053_test.py b/tests/bugs/core_2053_test.py index 3a09eb5f..03cc9f74 100644 --- a/tests/bugs/core_2053_test.py +++ b/tests/bugs/core_2053_test.py @@ -7,40 +7,48 @@ DESCRIPTION: JIRA: CORE-2053 FBTEST: bugs.core_2053 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t1 (col1 int); -create index i1 on t1 (col1); -commit; -insert into t1 (col1) values (1); -commit; -create table t2 (col2 int); -commit; -""" - -db = db_factory(init=init_script) +db = db_factory() -test_script = """SET PLAN ON; -insert into t2 (col2) values (1) returning case when exists (select 1 from t1 where col1 = col2) then 1 else 0 end; -commit;""" +test_script = """ + set list on; + create table t1 (col1 int); + create index i1 on t1 (col1); + commit; + insert into t1 (col1) values (1); + commit; + create table t2 (col2 int); + commit; -act = isql_act('db', test_script) + SET PLAN ON; + insert into t2 (col2) values (1) returning case when exists (select 1 from t1 where col1 = col2) then 1 else 0 end as insert_outcome; +""" -expected_stdout = """ -PLAN (T1 INDEX (I1)) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) - CASE -============ - 1 +expected_stdout_5x = """ + PLAN (T1 INDEX (I1)) + INSERT_OUTCOME 1 +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."I1")) + INSERT_OUTCOME 1 """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 0820241445d758a313d39b98a2b37ae917df968e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 15:43:02 +0300 Subject: [PATCH 0701/1064] Added/Updated tests\bugs\core_2073_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2073_test.py | 93 +++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/tests/bugs/core_2073_test.py b/tests/bugs/core_2073_test.py index 766abfe6..3276eed2 100644 --- a/tests/bugs/core_2073_test.py +++ b/tests/bugs/core_2073_test.py @@ -7,64 +7,69 @@ DESCRIPTION: JIRA: CORE-1000 FBTEST: bugs.core_2073 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE TMP_DATE1 -( - DATE1 DATE, - DATE2 DATE -); -COMMIT; -SET TERM !!; -EXECUTE BLOCK -AS - DECLARE VARIABLE D DATE; -BEGIN - D = '01.01.2008'; - WHILE (D < '01.08.2008') DO BEGIN - INSERT INTO TMP_DATE1(DATE1, DATE2) - VALUES(:D, :D + 100); - D = D + 1; - END -END!! -SET TERM ;!! -COMMIT; -CREATE INDEX TMP_DATE1_IDX1 ON TMP_DATE1 COMPUTED BY (DATE1+0); -CREATE INDEX TMP_DATE1_IDX2 ON TMP_DATE1 (DATE1); -COMMIT; -""" - -db = db_factory(init=init_script) +db = db_factory() -test_script = """SET PLAN ON; -SELECT count(*) FROM TMP_DATE1 T WHERE '01.03.2008' BETWEEN T.DATE1+0 AND T.DATE2; -SELECT count(*) FROM TMP_DATE1 T WHERE '01.03.2008' >= T.DATE1; -""" +test_script = """ + set list on; + create table tmp_date1 ( + date1 date, + date2 date + ); + commit; + set term ^; + execute block as + declare variable d date; + begin + d = '01.01.2008'; + while (d < '01.08.2008') do begin + insert into tmp_date1(date1, date2) values(:d, :d + 100); + d = d + 1; + end + end^ + set term ;^ + commit; -act = isql_act('db', test_script) + create index tmp_date1_idx1 on tmp_date1 computed by (date1+0); + create index tmp_date1_idx2 on tmp_date1 (date1); + commit; -expected_stdout = """ -PLAN (T INDEX (TMP_DATE1_IDX1)) + set plan on; + select count(*) from tmp_date1 t where '01.03.2008' between t.date1+0 and t.date2; + select count(*) from tmp_date1 t where '01.03.2008' >= t.date1; +""" - COUNT -===================== - 61 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -PLAN (T INDEX (TMP_DATE1_IDX2)) +expected_stdout_5x = """ + PLAN (T INDEX (TMP_DATE1_IDX1)) + COUNT 61 + PLAN (T INDEX (TMP_DATE1_IDX2)) + COUNT 61 - COUNT -===================== - 61 +""" +expected_stdout_6x = """ + PLAN ("T" INDEX ("PUBLIC"."TMP_DATE1_IDX1")) + COUNT 61 + PLAN ("T" INDEX ("PUBLIC"."TMP_DATE1_IDX2")) + COUNT 61 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From d452fb50d483901e6028de54d9bbdfc98612d965 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 16:34:40 +0300 Subject: [PATCH 0702/1064] Added/Updated tests\bugs\core_2132_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2132_test.py | 313 +++++++++++++++++++---------------- 1 file changed, 167 insertions(+), 146 deletions(-) diff --git a/tests/bugs/core_2132_test.py b/tests/bugs/core_2132_test.py index a95ef0a6..380abd4d 100644 --- a/tests/bugs/core_2132_test.py +++ b/tests/bugs/core_2132_test.py @@ -7,163 +7,184 @@ DESCRIPTION: JIRA: CORE-2132 FBTEST: bugs.core_2132 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t1 (col int primary key); -set term ^ ; -create procedure p1 returns (ret int) as begin ret = 0; suspend; end ^ -create procedure p2 (prm int) returns (ret int) as begin ret = prm; suspend; end ^ -set term ; ^ -commit; -insert into t1 (col) values (0); -commit; -""" - -db = db_factory(init=init_script) - -test_script = """set plan on ; - --- index -select * from t1 where col = 0; --- natural -select * from t1 where col = col; --- index -select * from t1 where col = ( select 0 from rdb$database ); --- natural -select * from t1 where col = ( select col from rdb$database ); --- index (currently natural) -select * from t1 where col = ( select 0 from p1 ); --- index (currently natural) -select * from t1 where col = ( select ret from p1 ); --- natural -select * from t1 where col = ( select col from p1 ); --- index (currently natural) -select * from t1 where col = ( select 0 from p2(0) ); --- index (currently natural) -select * from t1 where col = ( select ret from p2(0) ); --- natural -select * from t1 where col = ( select col from p2(0) ); --- natural -select * from t1 where col = ( select 0 from p2(col) ); --- natural -select * from t1 where col = ( select ret from p2(col) ); --- natural -select * from t1 where col = ( select col from p2(col) ); - +db = db_factory() + +test_script = """ + set list on; + create table t1 (col int primary key); + set term ^ ; + create procedure p1 returns (ret int) as begin ret = 0; suspend; end ^ + create procedure p2 (prm int) returns (ret int) as begin ret = prm; suspend; end ^ + set term ; ^ + commit; + insert into t1 (col) values (0); + commit; + + set plan on; + -- index + select 'point-01' msg, t1.* from t1 where col = 0; + + -- natural + select 'point-02' msg, t1.* from t1 where col = col; + + -- index + select 'point-03' msg, t1.* from t1 where col = ( select 0 from rdb$database ); + + -- natural + select 'point-04' msg, t1.* from t1 where col = ( select col from rdb$database ); + + -- index (currently natural) + select 'point-05' msg, t1.* from t1 where col = ( select 0 from p1 ); + + -- index (currently natural) + select 'point-06' msg, t1.* from t1 where col = ( select ret from p1 ); + + -- natural + select 'point-07' msg, t1.* from t1 where col = ( select col from p1 ); + + -- index (currently natural) + select 'point-08' msg, t1.* from t1 where col = ( select 0 from p2(0) ); + + -- index (currently natural) + select 'point-09' msg, t1.* from t1 where col = ( select ret from p2(0) ); + + -- natural + select 'point-10' msg, t1.* from t1 where col = ( select col from p2(0) ); + + -- natural + select 'point-11' msg, t1.* from t1 where col = ( select 0 from p2(col) ); + + -- natural + select 'point-12' msg, t1.* from t1 where col = ( select ret from p2(col) ); + + -- natural + select 'point-13' msg, t1.* from t1 where col = ( select col from p2(col) ); """ act = isql_act('db', test_script) -expected_stdout = """ -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (RDB$DATABASE NATURAL) -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (RDB$DATABASE NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (P1 NATURAL) -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (P1 NATURAL) -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (P1 NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 INDEX (RDB$PRIMARY1)) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 - - -PLAN (P2 NATURAL) -PLAN (T1 NATURAL) - - COL -============ - 0 +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-01 + COL 0 + PLAN (T1 NATURAL) + MSG point-02 + COL 0 + PLAN (RDB$DATABASE NATURAL) + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-03 + COL 0 + PLAN (RDB$DATABASE NATURAL) + PLAN (T1 NATURAL) + MSG point-04 + COL 0 + PLAN (P1 NATURAL) + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-05 + COL 0 + PLAN (P1 NATURAL) + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-06 + COL 0 + PLAN (P1 NATURAL) + PLAN (T1 NATURAL) + MSG point-07 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-08 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 INDEX (RDB$PRIMARY1)) + MSG point-09 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 NATURAL) + MSG point-10 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 NATURAL) + MSG point-11 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 NATURAL) + MSG point-12 + COL 0 + PLAN (P2 NATURAL) + PLAN (T1 NATURAL) + MSG point-13 + COL 0 +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-01 + COL 0 + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-02 + COL 0 + PLAN ("SYSTEM"."RDB$DATABASE" NATURAL) + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-03 + COL 0 + PLAN ("SYSTEM"."RDB$DATABASE" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-04 + COL 0 + PLAN ("PUBLIC"."P1" NATURAL) + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-05 + COL 0 + PLAN ("PUBLIC"."P1" NATURAL) + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-06 + COL 0 + PLAN ("PUBLIC"."P1" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-07 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-08 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" INDEX ("PUBLIC"."RDB$PRIMARY1")) + MSG point-09 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-10 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-11 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-12 + COL 0 + PLAN ("PUBLIC"."P2" NATURAL) + PLAN ("PUBLIC"."T1" NATURAL) + MSG point-13 + COL 0 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 37a98b6066046973729467bebf9fb85e7c7a0143 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 16:36:26 +0300 Subject: [PATCH 0703/1064] Added/Updated tests\bugs\core_2132_test.py: minor change: removed old assignment --- tests/bugs/core_2132_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/bugs/core_2132_test.py b/tests/bugs/core_2132_test.py index 380abd4d..060cbeb1 100644 --- a/tests/bugs/core_2132_test.py +++ b/tests/bugs/core_2132_test.py @@ -72,8 +72,6 @@ select 'point-13' msg, t1.* from t1 where col = ( select col from p2(col) ); """ -act = isql_act('db', test_script) - substitutions = [('[ \t]+', ' ')] act = isql_act('db', test_script, substitutions = substitutions) From 0e721f00cf74be50e06c846fabb4835bf4c34274 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 16:53:28 +0300 Subject: [PATCH 0704/1064] Added/Updated tests\bugs\core_2140_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2140_test.py | 91 +++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 28 deletions(-) diff --git a/tests/bugs/core_2140_test.py b/tests/bugs/core_2140_test.py index 84ae6c31..38439e70 100644 --- a/tests/bugs/core_2140_test.py +++ b/tests/bugs/core_2140_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2140 FBTEST: bugs.core_2140 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,36 +20,65 @@ db = db_factory() -test_script = """ - set list on; - set term ^ ; - execute block returns (y int) as - begin - for execute statement - ('select rdb$relation_id from rdb$database where rdb$relation_id = :x') (1) - with autonomous transaction - into y - do suspend; - end ^ -""" +substitutions = [ + ('Data source : Firebird::.*', 'Data source : Firebird::'), + ('col(umn)?(:)?.*', 'col x'), + ('-At block line: [\\d]+, col: [\\d]+', '') +] -act = isql_act('db', test_script, - substitutions=[('column.*', 'column x'), - ('-At block line: [\\d]+, col: [\\d]+', '')]) - -expected_stderr = """ - Statement failed, SQLSTATE = 42S22 - Dynamic SQL Error - -SQL error code = -206 - -Column unknown - -X - -At line 1, column 67 - -At block line: 5, col: 3 -""" +act = isql_act('db', substitutions = substitutions) @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + # Statement that will be passed in ES/EDS (we have to check its presence in error message): + EDS_STATEMENT = 'select rdb$relation_id from rdb$database where rdb$relation_id = :x' + + test_script = f""" + set list on; + set term ^ ; + execute block returns (y int) as + begin + for + execute statement ('{EDS_STATEMENT}') (1) + on external 'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME') + as user '{act.db.user}' password '{act.db.password}' + with autonomous transaction + into y + do suspend; + end + ^ + """ + + # BEFOREE fix output was: + # Statement : select rdb$relation_id from rdb$database where rdb$relation_id = :x\nData source : Internal::. + + expected_stdout_5x = f""" + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544569 : Dynamic SQL Error + 335544436 : SQL error code = -206 + 335544578 : Column unknown + 335544382 : X + 336397208 : At line 1, column 66 + Statement : {EDS_STATEMENT} + Data source : Firebird:: + -At block line: 3, col: 11 + """ + + expected_stdout_6x = f""" + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544569 : Dynamic SQL Error + 335544436 : SQL error code = -206 + 335544578 : Column unknown + 335544382 : "X" + 336397208 : At line 1, column 66 + Statement : {EDS_STATEMENT} + Data source : Firebird:: + -At block line: 3, col: 11 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From dfdb02c64c4a1c8c1791dfa102babdbdae24f142 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 17:00:13 +0300 Subject: [PATCH 0705/1064] Added/Updated tests\bugs\core_2140_test.py: minor change: added marker --- tests/bugs/core_2140_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_2140_test.py b/tests/bugs/core_2140_test.py index 38439e70..50d62b50 100644 --- a/tests/bugs/core_2140_test.py +++ b/tests/bugs/core_2140_test.py @@ -28,6 +28,7 @@ act = isql_act('db', substitutions = substitutions) +@pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): From b3208e4bd1b4ac17545dd84f8f2a1fc8a609e65e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 17:02:36 +0300 Subject: [PATCH 0706/1064] Added/Updated tests\bugs\core_2155_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2155_test.py | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_2155_test.py b/tests/bugs/core_2155_test.py index df2adbae..63a828e7 100644 --- a/tests/bugs/core_2155_test.py +++ b/tests/bugs/core_2155_test.py @@ -7,12 +7,20 @@ DESCRIPTION: JIRA: CORE-2155 FBTEST: bugs.core_2155 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ set term ^; create or alter procedure sp_test(a_id int) returns (a_dup int) as begin @@ -30,11 +38,7 @@ select dummy_alias.rdb$relation_id, dummy_alias.rdb$field_id from rdb$relations as dummy_alias; commit; -""" - -db = db_factory(init=init_script) -test_script = """ set planonly; select v.rdb$relation_id, p.* @@ -46,16 +50,21 @@ INNER join sp_test(v.rdb$field_id) p on 1=1; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (V RDB$RELATIONS NATURAL, P NATURAL) PLAN JOIN (V DUMMY_ALIAS NATURAL, P NATURAL) """ -@pytest.mark.version('>=3.0') +expected_stdout_6x = """ + PLAN JOIN ("V" "SYSTEM"."RDB$RELATIONS" NATURAL, "P" NATURAL) + PLAN JOIN ("V" "DUMMY_ALIAS" NATURAL, "P" NATURAL) +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From a8372183a246ae64ff3118245ea67ce818359bbf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 17:53:49 +0300 Subject: [PATCH 0707/1064] Added/Updated tests\bugs\core_2200_test.py: Re-implemented - see notes. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2200_test.py | 126 ++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 38 deletions(-) diff --git a/tests/bugs/core_2200_test.py b/tests/bugs/core_2200_test.py index add0c0ee..0218b1cf 100644 --- a/tests/bugs/core_2200_test.py +++ b/tests/bugs/core_2200_test.py @@ -7,6 +7,20 @@ DESCRIPTION: JIRA: CORE-2200 FBTEST: bugs.core_2200 +NOTES: + [26.06.2025] pzotov + Re-implemented to be more relevant with: + https://github.com/FirebirdSQL/firebird/issues/2628#issuecomment-826197753 + (Improve the cross join algorithm to stop as soon as any of the involved streams is detected as empty). + No matter how many tables are involved in the cross join, its plan must always start from EMPTY table. + We create here six tables and fill five of them. Table 't6' remains empty. + We check that in all queries where this table present in different position execution plans starts + with name of this table. + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,57 +32,93 @@ -- Confirmed: wrong plan on 2.0.0.12724 and 2.1.0.17798: 'T2' was choosen as drive source, -- absence of rows in T3 was ignored, used: PLAN JOIN (T2 NATURAL, T1 NATURAL, T3 NATURAL) - recreate table t0(id int); + set list on; recreate table t1(id int); recreate table t2(id int); recreate table t3(id int); + recreate table t4(id int); + recreate table t5(id int); + recreate table t6(id int); + set term ^; + create procedure sp_gen_rows( a_cnt int ) returns ( i int ) as + begin + i = 0; + while (i < a_cnt ) do + begin + suspend; + i = i + 1; + end + end + ^ + set term ;^ commit; - insert into t0 select 1 from rdb$types; -- ,rdb$types; - commit; - - - insert into t1 select * from t0; - insert into t2 select * from t0; - --------- ::: NB ::: we do NOT add any row to the table `t3`, it remains empty ----------- + insert into t1 select p.i from sp_gen_rows( 1000 + rand() * 9000 ) as p; + insert into t2 select p.i from sp_gen_rows( 1000 + rand() * 9000 ) as p; + insert into t3 select p.i from sp_gen_rows( 1000 + rand() * 9000 ) as p; + insert into t4 select p.i from sp_gen_rows( 1000 + rand() * 9000 ) as p; + insert into t5 select p.i from sp_gen_rows( 1000 + rand() * 9000 ) as p; + -- ::: NB ::: we do NOT add any row to the table `t6`, it remains empty commit; - set list on; - select case when count(*) > 100 then 'OK' else 'WRONG' end as t1_has_enough_rows from t1; - select case when count(*) > 100 then 'OK' else 'WRONG' end as t2_has_enough_rows from t2; - - set plan on; - set echo on; - - select count(*) from t1, t2, t3; - - select count(*) from t2, t3, t1; - - select count(*) from t3, t2, t1; + select + sign( (select count(*) from t1) - 1000 ) t1_big_enough + ,sign( (select count(*) from t2) - 1000 ) t2_big_enough + ,sign( (select count(*) from t3) - 1000 ) t3_big_enough + ,sign( (select count(*) from t4) - 1000 ) t4_big_enough + ,sign( (select count(*) from t5) - 1000 ) t5_big_enough + ,(select count(*) from t6) t6_rows_count + from rdb$database; + + set planonly; + select count(*) from t1, t2, t3, t4, t5, t6; + select count(*) from t1, t2, t3, t4, t6, t5; + select count(*) from t1, t2, t3, t6, t5, t4; + select count(*) from t1, t2, t6, t4, t5, t3; + select count(*) from t1, t6, t3, t4, t5, t2; + select count(*) from t6, t2, t3, t4, t5, t1; """ -act = isql_act('db', test_script) - -expected_stdout = """ - T1_HAS_ENOUGH_ROWS OK - T2_HAS_ENOUGH_ROWS OK - select count(*) from t1, t2, t3; - PLAN JOIN (T3 NATURAL, T1 NATURAL, T2 NATURAL) - COUNT 0 - - select count(*) from t2, t3, t1; - PLAN JOIN (T3 NATURAL, T2 NATURAL, T1 NATURAL) - COUNT 0 +substitutions = [ + ('[ \t]+', ' '), + (r'PLAN JOIN \(T6 NATURAL.*', 'PLAN JOIN (T6 NATURAL'), + (r'PLAN JOIN \("PUBLIC"."T6" NATURAL.*', 'PLAN JOIN ("PUBLIC"."T6" NATURAL') +] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + T1_BIG_ENOUGH 1 + T2_BIG_ENOUGH 1 + T3_BIG_ENOUGH 1 + T4_BIG_ENOUGH 1 + T5_BIG_ENOUGH 1 + T6_ROWS_COUNT 0 + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T1 NATURAL, T3 NATURAL) + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T1 NATURAL, T3 NATURAL) + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T1 NATURAL, T3 NATURAL) + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T1 NATURAL, T3 NATURAL) + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T1 NATURAL, T3 NATURAL) + PLAN JOIN (T6 NATURAL, T2 NATURAL, T4 NATURAL, T5 NATURAL, T3 NATURAL, T1 NATURAL) +""" - select count(*) from t3, t2, t1; - PLAN JOIN (T3 NATURAL, T2 NATURAL, T1 NATURAL) - COUNT 0 +expected_stdout_6x = """ + T1_BIG_ENOUGH 1 + T2_BIG_ENOUGH 1 + T3_BIG_ENOUGH 1 + T4_BIG_ENOUGH 1 + T5_BIG_ENOUGH 1 + T6_ROWS_COUNT 0 + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T2" NATURAL) + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T2" NATURAL) + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T2" NATURAL) + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T2" NATURAL) + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T2" NATURAL) + PLAN JOIN ("PUBLIC"."T6" NATURAL, "PUBLIC"."T5" NATURAL, "PUBLIC"."T4" NATURAL, "PUBLIC"."T3" NATURAL, "PUBLIC"."T1" NATURAL, "PUBLIC"."T2" NATURAL) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From fe51d30e8f70f8c857b9162d7b82529decedeb7b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 18:37:52 +0300 Subject: [PATCH 0708/1064] Added/Updated tests\bugs\core_2202_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2202_test.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_2202_test.py b/tests/bugs/core_2202_test.py index 9f0c609c..10f6dc8c 100644 --- a/tests/bugs/core_2202_test.py +++ b/tests/bugs/core_2202_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2202 FBTEST: bugs.core_2202 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -46,18 +52,25 @@ from rdb$view_relations rv; """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + VEW_NAME VW_TABLE + REL_NAME TABLE_3 + RDB$VIEW_CONTEXT 1 + CTX_NAME TABLE_3 +""" -expected_stdout = """ - VEW_NAME VW_TABLE - REL_NAME TABLE_3 - RDB$VIEW_CONTEXT 1 - CTX_NAME TABLE_3 +expected_stdout_6x = """ + VEW_NAME VW_TABLE + REL_NAME TABLE_3 + RDB$VIEW_CONTEXT 1 + CTX_NAME "PUBLIC"."TABLE_3" """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 35d246bedab08ba4f03c3b1bd5d7ad341104a93b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 18:41:27 +0300 Subject: [PATCH 0709/1064] Added/Updated tests\bugs\core_2216_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_2216_test.py | 55 +++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_2216_test.py b/tests/bugs/core_2216_test.py index 9f180b1f..009e574e 100644 --- a/tests/bugs/core_2216_test.py +++ b/tests/bugs/core_2216_test.py @@ -15,6 +15,12 @@ 2. Run online validation of - it sould NOT produce any errors. JIRA: CORE-2216 FBTEST: bugs.core_2216 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -23,8 +29,8 @@ from firebird.driver import SrvNBackupFlag substitutions = [('BLOB_ID.*', ''), - ('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), - ('Relation [0-9]{3,4}', 'Relation')] + ('\\d\\d:\\d\\d:\\d\\d.\\d\\d', ''), + ('Relation \\d{3,4}', 'Relation')] init_script = """ create table test(id int, s varchar(10) unique using index test_s, t timestamp, b blob); @@ -37,25 +43,36 @@ nbak_file_base = temp_file('nbak-file.fdb') nbak_file_add = temp_file('nbak-file.add') -expected_stdout_a = """ - ID 1 - S qwerty - T 2013-12-11 14:15:16.1780 - foo-rio-bar - Records affected: 1 -""" - -expected_stdout_b = """ - Validation started - Relation (TEST) - process pointer page 0 of 1 - Index 1 (TEST_S) - Relation (TEST) is ok - Validation finished -""" - @pytest.mark.version('>=4.0') def test_1(act: Action, nbak_file_base: Path, nbak_file_add: Path): + + expected_stdout_a = """ + ID 1 + S qwerty + T 2013-12-11 14:15:16.1780 + foo-rio-bar + Records affected: 1 + """ + + if act.is_version('<6'): + expected_stdout_b = """ + Validation started + Relation (TEST) + process pointer page 0 of 1 + Index 1 (TEST_S) + Relation (TEST) is ok + Validation finished + """ + else: + expected_stdout_b = """ + Validation started + Relation ("PUBLIC"."TEST") + process pointer page 0 of 1 + Index 1 ("PUBLIC"."TEST_S") + Relation ("PUBLIC"."TEST") is ok + Validation finished + """ + with act.connect_server() as srv, act.db.connect() as con: # Backup base database srv.database.nbackup(database=act.db.db_path, backup=nbak_file_base, From 1d875f763dfc1ff63001d17c746f403221086697 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 18:53:46 +0300 Subject: [PATCH 0710/1064] Added/Updated tests\bugs\core_2230_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2230_test.py | 54 ++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_2230_test.py b/tests/bugs/core_2230_test.py index 4e370f17..66b60c1b 100644 --- a/tests/bugs/core_2230_test.py +++ b/tests/bugs/core_2230_test.py @@ -7,34 +7,54 @@ DESCRIPTION: JIRA: CORE-2230 FBTEST: bugs.core_2230 +NOTES: + [26.06.2025] pzotov + Slightly refactored: made code more readable. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * from firebird.driver import DatabaseError -init_script = """CREATE DOMAIN DOM1 AS INTEGER NOT NULL CHECK (value in (0, 1)); +init_script = """ + create domain dm_test as integer not null check (value in (0, 1)); """ db = db_factory(init=init_script) - act = python_act('db') -expected_stdout = """Y ------------ -1 -""" - @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): with act.db.connect() as con: - c = con.cursor() - cmd = c.prepare('execute block (x DOM1 = ?) returns (y integer) as begin y = x; suspend; end') - c.execute(cmd, [1]) - act.print_data(c) - act.expected_stdout = expected_stdout - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - with pytest.raises(Exception, match='.*validation error for variable X, value "10"'): - c.execute(cmd, [10]) - act.print_data(c) + cur = con.cursor() + ps = cur.prepare('execute block (a_input_value dm_test = ?) returns (y integer) as begin y = a_input_value; suspend; end') + try: + for x in (1, 11): + cur.execute(ps, (x,)) + for r in cur: + print(r[0]) + except DatabaseError as e: + print(e.__str__()) + for x in e.gds_codes: + print(x) + + + expected_stdout_5x = """ + 1 + validation error for variable A_INPUT_VALUE, value "11" + 335544879 + """ + + expected_stdout_6x = """ + 1 + validation error for variable "A_INPUT_VALUE", value "11" + 335544879 + """ + 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 From 08f0a6ce218088e146116aa37ffe5deeacba7025 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 18:56:44 +0300 Subject: [PATCH 0711/1064] Added/Updated tests\bugs\core_2289_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2289_test.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2289_test.py b/tests/bugs/core_2289_test.py index ee0a36c5..f41ccbc8 100644 --- a/tests/bugs/core_2289_test.py +++ b/tests/bugs/core_2289_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2289 FBTEST: bugs.core_2289 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,16 +38,22 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 violation of FOREIGN KEY constraint "PACKET_DETAIL_FK" on table "PACKET_DETAIL" -Foreign key reference target does not exist -Problematic key value is ("PACKET_ID" = 753) """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "PACKET_DETAIL_FK" on table "PUBLIC"."PACKET_DETAIL" + -Foreign key reference target does not exist + -Problematic key value is ("PACKET_ID" = 753) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e05405633e507a6e92110572f42843cdc9cc452d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 19:26:45 +0300 Subject: [PATCH 0712/1064] Added/Updated tests\bugs\core_2303_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2303_test.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2303_test.py b/tests/bugs/core_2303_test.py index a0969bf6..770f2f52 100644 --- a/tests/bugs/core_2303_test.py +++ b/tests/bugs/core_2303_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-2303 FBTEST: bugs.core_2303 +NOTES: + [26.06.2025] pzotov + Slightly refactored: made code more readable. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,11 +23,6 @@ act = python_act('db') TAG_TEXT = 'TAG_FOR_SEARCH' -expected_stdout = f""" - select 1 /* {TAG_TEXT} */ from rdb$database - Select Expression - -> Table "RDB$DATABASE" Full Scan -""" @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): @@ -33,6 +35,20 @@ def test_1(act: Action, capsys): print(r[0]) print(r[1]) + + expected_stdout_5x = f""" + select 1 /* {TAG_TEXT} */ from rdb$database + Select Expression + -> Table "RDB$DATABASE" Full Scan + """ + + expected_stdout_6x = f""" + select 1 /* {TAG_TEXT} */ from rdb$database + Select Expression + -> Table "SYSTEM"."RDB$DATABASE" Full Scan + """ + expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 6ee68605d72f525bb08bdb97fdaed4ce332097b2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 20:29:41 +0300 Subject: [PATCH 0713/1064] Added/Updated tests\bugs\core_2374_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2374_test.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_2374_test.py b/tests/bugs/core_2374_test.py index 87851427..7bd3baa7 100644 --- a/tests/bugs/core_2374_test.py +++ b/tests/bugs/core_2374_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2374 FBTEST: bugs.core_2374 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -33,20 +39,32 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -ALTER PROCEDURE TEST1 failed -Procedure TEST1 not found + Statement failed, SQLSTATE = 42000 unsuccessful metadata update -ALTER TRIGGER TRG1 failed -Trigger TRG1 not found """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER PROCEDURE "PUBLIC"."TEST1" failed + -Procedure "PUBLIC"."TEST1" not found + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TRIGGER "PUBLIC"."TRG1" failed + -Trigger "PUBLIC"."TRG1" not found +""" + +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 2a26e08e1360e9ca305ac7536b09756f306d0189 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 20:32:57 +0300 Subject: [PATCH 0714/1064] Added/Updated tests\bugs\core_2386_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2386_test.py | 69 +++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/tests/bugs/core_2386_test.py b/tests/bugs/core_2386_test.py index 1d12a29f..93018147 100644 --- a/tests/bugs/core_2386_test.py +++ b/tests/bugs/core_2386_test.py @@ -7,48 +7,59 @@ DESCRIPTION: JIRA: CORE-2386 FBTEST: bugs.core_2386 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """SET TERM ^ ; - -CREATE VIEW V_TEST (F1, F2) -AS - SELECT 1, 2 FROM RDB$DATABASE -^ - -CREATE PROCEDURE SP_TEST -AS -DECLARE I INT; -BEGIN - SELECT F1, F2 FROM V_TEST - INTO :I, :I; -END -^ - -COMMIT -^ +init_script = """ """ db = db_factory(init=init_script) -test_script = """ALTER VIEW V_TEST (F1) AS - SELECT 1 FROM RDB$DATABASE ;""" +test_script = """ + set term ^ ; + create view v_test (f1, f2) as select 1, 2 from rdb$database + ^ + create procedure sp_test as + declare i int; + begin + select f1, f2 from v_test into :i, :i; + end + ^ + commit + ^ + alter view v_test (f1) as select 1 from rdb$database + ^ + +""" act = isql_act('db', test_script) -expected_stderr = """Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --cannot delete --COLUMN V_TEST.F2 --there are 1 dependencies +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN V_TEST.F2 + -there are 1 dependencies +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."V_TEST"."F2" + -there are 1 dependencies """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 052c4ae9ac0116f73bf239f82bdd2efcfc5b818a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 20:49:33 +0300 Subject: [PATCH 0715/1064] Added/Updated tests\bugs\core_2424_test.py: Reimplemented - see notes. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2424_test.py | 37 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_2424_test.py b/tests/bugs/core_2424_test.py index 3478ad94..5e91ef9b 100644 --- a/tests/bugs/core_2424_test.py +++ b/tests/bugs/core_2424_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-2424 FBTEST: bugs.core_2424 +NOTES: + [26.06.2025] pzotov + Reimplemented. It is enough just to try to run command CREATE VIEW with check presence + of appropriate record in RDB$RELATIONS. + No need in 'SHOW VIEW'. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,27 +21,25 @@ db = db_factory() -test_script = """create view V as select d.rdb$relation_id from rdb$database d group by d.rdb$relation_id; -show view v; -recreate view V as select a from (select 1 a from rdb$database); -show view v; +test_script = """ + set list on; + create view v_test as + select d.rdb$relation_id + from rdb$database d + group by d.rdb$relation_id; + commit; + select count(*) as view_created from rdb$relations where rdb$relation_name = upper('v_test'); """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """RDB$RELATION_ID SMALLINT Expression -View Source: -==== ====== - select d.rdb$relation_id from rdb$database d group by d.rdb$relation_id -A INTEGER Expression -View Source: -==== ====== - select a from (select 1 a from rdb$database) +expected_stdout = """ + VIEW_CREATED 1 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 24fb71aaeb8a65c3a1945d2306d064229f425816 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 20:53:57 +0300 Subject: [PATCH 0716/1064] Added/Updated tests\bugs\core_2430_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2430_test.py | 46 ++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_2430_test.py b/tests/bugs/core_2430_test.py index 3fe82320..a6053c50 100644 --- a/tests/bugs/core_2430_test.py +++ b/tests/bugs/core_2430_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2430 FBTEST: bugs.core_2430 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,29 +20,39 @@ db = db_factory() -test_script = """CREATE TABLE T1 ( - F1 BIGINT NOT NULL, - F2 BIGINT NOT NULL, - F3 TIMESTAMP DEFAULT current_timestamp NOT NULL -); +test_script = """ + create table t1 ( + f1 bigint not null, + f2 bigint not null, + f3 timestamp default current_timestamp not null + ); -ALTER TABLE T1 ADD CONSTRAINT PK_T1 PRIMARY KEY (F1, F2); + alter table t1 add constraint pk_t1 primary key (f1, f2); -show table t1; + show table t1; """ act = isql_act('db', test_script) -expected_stdout = """F1 BIGINT Not Null -F2 BIGINT Not Null -F3 TIMESTAMP Not Null DEFAULT current_timestamp -CONSTRAINT PK_T1: - Primary key (F1, F2) +expected_stdout_5x = """ + F1 BIGINT Not Null + F2 BIGINT Not Null + F3 TIMESTAMP Not Null default current_timestamp + CONSTRAINT PK_T1: + Primary key (F1, F2) +""" + +expected_stdout_6x = """ + Table: PUBLIC.T1 + F1 BIGINT Not Null + F2 BIGINT Not Null + F3 TIMESTAMP Not Null default current_timestamp + CONSTRAINT PK_T1: + Primary key (F1, F2) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 57b0967f99da5c5d5d9161323e9dcb318a55fa9f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 20:58:44 +0300 Subject: [PATCH 0717/1064] Added/Updated tests\bugs\core_2431_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2431_test.py | 37 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_2431_test.py b/tests/bugs/core_2431_test.py index c0e17e2a..9cedd3b9 100644 --- a/tests/bugs/core_2431_test.py +++ b/tests/bugs/core_2431_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2431 FBTEST: bugs.core_2431 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,26 +37,29 @@ commit; """ -act = isql_act('db', test_script, - substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) +substitutions = [ ('[ \t]+', ' '), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - CONNECTION_CSET WIN1251 +expected_stdout_5x = """ + CONNECTION_CSET WIN1251 + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_BAD_REMAINDER + -Новый остаток изделия будет отрицательным: -8 + -At block line """ -expected_stderr = """ +expected_stdout_6x = """ + CONNECTION_CSET WIN1251 Statement failed, SQLSTATE = HY000 exception 1 - -EX_BAD_REMAINDER + -"PUBLIC"."EX_BAD_REMAINDER" -Новый остаток изделия будет отрицательным: -8 - -At block line: 3, col: 7 + -At block line """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute(charset='win1251') - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(charset='win1251', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From ecd7b6261bd82320212f2649be71f24ecebab42e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:01:42 +0300 Subject: [PATCH 0718/1064] Added/Updated tests\bugs\core_2508_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2508_test.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2508_test.py b/tests/bugs/core_2508_test.py index d150a8db..83c01d25 100644 --- a/tests/bugs/core_2508_test.py +++ b/tests/bugs/core_2508_test.py @@ -16,6 +16,12 @@ Old query that did use IN predicate no more applicable here: all occurences of the same index that works for mining data are now "collapsed" to the single one, i.e.: PLAN ( INDEX (, , )) ==> PLAN ( INDEX ()). + + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -42,14 +48,19 @@ -- PLAN (T INDEX (abc(, mod()) """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' '), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN (T INDEX (abc(, mod()) """ -@pytest.mark.version('>=3.0') +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."abc(", "PUBLIC"."mod(")) +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 66fa477d844e2b233f99fc758c9003ed5ee80b10 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:04:50 +0300 Subject: [PATCH 0719/1064] Added/Updated tests\bugs\core_2516_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2516_test.py | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_2516_test.py b/tests/bugs/core_2516_test.py index f9b93806..aa0a455f 100644 --- a/tests/bugs/core_2516_test.py +++ b/tests/bugs/core_2516_test.py @@ -3,36 +3,37 @@ """ ID: issue-2926 ISSUE: 2926 -TITLE: Wrong processing a SP parameters with arrays +TITLE: Wrong processing SP parameters with arrays DESCRIPTION: JIRA: CORE-2516 FBTEST: bugs.core_2516 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - create domain t_smallint_array as smallint [0:2]; -""" - -db = db_factory(init=init_script) +db = db_factory() test_script = """ + create domain t_smallint_array as smallint [0:2]; set term ^; - create procedure sp_smallint_array(x t_smallint_array) - returns (y t_smallint_array) - as + create procedure sp_smallint_array(x t_smallint_array) returns (y t_smallint_array) as begin - y=x; - suspend; + y=x; + suspend; end - ^ set term ;^ + ^ """ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 0A000 CREATE PROCEDURE SP_SMALLINT_ARRAY failed -Dynamic SQL Error @@ -40,9 +41,16 @@ -Usage of domain or TYPE OF COLUMN of array type in PSQL """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 0A000 + CREATE PROCEDURE "PUBLIC"."SP_SMALLINT_ARRAY" failed + -Dynamic SQL Error + -feature is not supported + -Usage of domain or TYPE OF COLUMN of array type in PSQL +""" +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 9a167d7716943429e99cad4d68fbf0ceb88ce2a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:07:50 +0300 Subject: [PATCH 0720/1064] Added/Updated tests\bugs\core_2555_test.py: Removed 'set plan on' - no needed in this test. --- tests/bugs/core_2555_test.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/bugs/core_2555_test.py b/tests/bugs/core_2555_test.py index 7cf4e7ca..94a7471b 100644 --- a/tests/bugs/core_2555_test.py +++ b/tests/bugs/core_2555_test.py @@ -61,7 +61,6 @@ commit; set list on; - set plan on; -- First, we check result of NATURAL scans: select rk from test group by ca,cb,rk; @@ -78,7 +77,6 @@ create unique index test_unq2 on test(cb, rk, ca, id); commit; - set plan on; select rk from test group by ca,cb,rk; select rk from test group by cb,rk,ca; """ @@ -87,7 +85,6 @@ expected_stdout = """ - PLAN SORT (TEST NATURAL) RK a RK c RK d @@ -97,7 +94,6 @@ RK s RK u - PLAN (TEST ORDER TEST_UNQ1) RK a RK c RK d @@ -107,7 +103,6 @@ RK s RK u - PLAN (TEST ORDER TEST_UNQ2) RK a RK c RK d From 9c2589e8a661095805965d14d474d30db8f020d7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:12:59 +0300 Subject: [PATCH 0721/1064] Added/Updated tests\bugs\core_2635_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2635_test.py | 113 ++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/tests/bugs/core_2635_test.py b/tests/bugs/core_2635_test.py index 4db0edac..0ff116f4 100644 --- a/tests/bugs/core_2635_test.py +++ b/tests/bugs/core_2635_test.py @@ -7,70 +7,89 @@ DESCRIPTION: JIRA: CORE-2635 FBTEST: bugs.core_2635 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """set term ^; -recreate table t (id int, sss varchar(255)) ^ -create unique descending index t_id_desc on t (id) ^ -create unique ascending index t_id_asc on t (id) ^ -create unique descending index t_id_sss_desc on t (id, sss) ^ -create unique ascending index t_id_sss_asc on t (id, sss) ^ -commit ^ +init_script = """ + set term ^; + recreate table t (id int, sss varchar(255)) ^ + create unique descending index t_id_desc on t (id) ^ + create unique ascending index t_id_asc on t (id) ^ + create unique descending index t_id_sss_desc on t (id, sss) ^ + create unique ascending index t_id_sss_asc on t (id, sss) ^ + commit ^ -execute block as -declare n int = 0; -begin - while (n < 10000) do - begin - insert into t values (:n, :n); - n = n + 1; - end + execute block as + declare n int = 0; + begin + while (n < 10000) do + begin + insert into t values (:n, :n); + n = n + 1; + end - n = 0; - while (n < 10000) do - begin - insert into t values (null, null); - n = n + 1; - end -end ^ -commit ^ + n = 0; + while (n < 10000) do + begin + insert into t values (null, null); + n = n + 1; + end + end ^ + commit ^ -execute block as -declare n int = 5000; -begin - while (n > 0) do - begin - n = n - 1; - update t set id = null, sss = null where id = :n; - end -end ^ -commit ^ + execute block as + declare n int = 5000; + begin + while (n > 0) do + begin + n = n - 1; + update t set id = null, sss = null where id = :n; + end + end ^ + commit ^ """ db = db_factory(init=init_script) -act = python_act('db', substitutions=[('[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9]', ''), - ('Relation [0-9]{3,4}', 'Relation')]) +act = python_act('db', substitutions=[ ('[ \t]+', ' '), ('\\d\\d:\\d\\d:\\d\\d.\\d\\d', ''), ('Relation \\d{3,4}', 'Relation')]) + +expected_stdout_5x = """ + Validation started + Relation (T) + process pointer page 0 of 1 + Index 1 (T_ID_DESC) + Index 2 (T_ID_ASC) + Index 3 (T_ID_SSS_DESC) + Index 4 (T_ID_SSS_ASC) + Relation (T) is ok + Validation finished +""" -expected_stdout = """ -Validation started -Relation (T) -process pointer page 0 of 1 -Index 1 (T_ID_DESC) -Index 2 (T_ID_ASC) -Index 3 (T_ID_SSS_DESC) -Index 4 (T_ID_SSS_ASC) -Relation (T) is ok -Validation finished +expected_stdout_6x = """ + Validation started + Relation ("PUBLIC"."T") + process pointer page 0 of 1 + Index 1 ("PUBLIC"."T_ID_DESC") + Index 2 ("PUBLIC"."T_ID_ASC") + Index 3 ("PUBLIC"."T_ID_SSS_DESC") + Index 4 ("PUBLIC"."T_ID_SSS_ASC") + Relation ("PUBLIC"."T") is ok + Validation finished """ -@pytest.mark.version('>=2.5') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x with act.connect_server() as srv: srv.database.validate(database=act.db.db_path) act.stdout = '\n'.join(srv.readlines()) + assert act.clean_stdout == act.clean_expected_stdout From beecb271e31c3fbd407dba277650045419d10f62 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:35:49 +0300 Subject: [PATCH 0722/1064] Updated tests\bugs\core_2650_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_2650_test.py | 239 ++++++++++++++++------------------- 1 file changed, 111 insertions(+), 128 deletions(-) diff --git a/tests/bugs/core_2650_test.py b/tests/bugs/core_2650_test.py index 88d0745d..45311ea7 100644 --- a/tests/bugs/core_2650_test.py +++ b/tests/bugs/core_2650_test.py @@ -858,309 +858,292 @@ 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 + {query_map[1000][0]} + {query_map[1000][1]} Select Expression ....-> Sort (record length: 1036, key length: 8) - ........-> Table "TEST" as "A01" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[1010][0]} + {query_map[1010][1]} Select Expression ....-> Refetch ........-> Sort (record length: 28, key length: 8) - ............-> Table "TEST" as "A02" Full Scan + ............-> Table "PUBLIC"."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 presents + {query_map[1020][0]} + {query_map[1020][1]} Select Expression ....-> First N Records ........-> Refetch ............-> Sort (record length: 28, key length: 8) - ................-> Table "TEST" as "A03" Full Scan + ................-> Table "PUBLIC"."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 + {query_map[2000][0]} + {query_map[2000][1]} Select Expression ....-> Sort (record length: 1036, key length: 8) - ........-> Table "TEST" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[2010][0]} + {query_map[2010][1]} Select Expression ....-> Refetch ........-> Sort (record length: 28, key length: 8) - ............-> Table "TEST" Full Scan + ............-> Table "PUBLIC"."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 *** + {query_map[3000][0]} + {query_map[3000][1]} Sub-query (invariant) ....-> Filter ........-> Sort (record length: 1036, key length: 8) ............-> Filter - ................-> Table "TEST" as "X04" Full Scan + ................-> Table "PUBLIC"."TEST" as "X04" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A04" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3010][0]} + {query_map[3010][1]} Sub-query (invariant) ....-> Filter ........-> Refetch ............-> Sort (record length: 28, key length: 8) ................-> Filter - ....................-> Table "TEST" as "X05" Full Scan + ....................-> Table "PUBLIC"."TEST" as "X05" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A05" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3020][0]} + {query_map[3020][1]} Sub-query (invariant) ....-> Sort (record length: 1036, key length: 8) ........-> Filter - ............-> Table "TEST" as "X06" Full Scan + ............-> Table "PUBLIC"."TEST" as "X06" Full Scan Sub-query (invariant) ....-> Sort (record length: 1036, key length: 8) ........-> Filter - ............-> Table "TEST" as "X06" Full Scan + ............-> Table "PUBLIC"."TEST" as "X06" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A06" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3030][0]} + {query_map[3030][1]} Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "X07" Full Scan + ................-> Table "PUBLIC"."TEST" as "X07" Full Scan Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "X07" Full Scan + ................-> Table "PUBLIC"."TEST" as "X07" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A07" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3040][0]} + {query_map[3040][1]} Sub-query (invariant) ....-> Filter ........-> Sort (record length: 1036, key length: 8) ............-> Filter - ................-> Table "TEST" as "X08" Full Scan + ................-> Table "PUBLIC"."TEST" as "X08" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A08" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3050][0]} + {query_map[3050][1]} Sub-query (invariant) ....-> Filter ........-> Refetch ............-> Sort (record length: 28, key length: 8) ................-> Filter - ....................-> Table "TEST" as "X09" Full Scan + ....................-> Table "PUBLIC"."TEST" as "X09" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A09" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3060][0]} + {query_map[3060][1]} Sub-query (invariant) ....-> Filter ........-> Sort (record length: 1036, key length: 8) ............-> Filter - ................-> Table "TEST" as "X10" Full Scan + ................-> Table "PUBLIC"."TEST" as "X10" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A10" Full Scan + ........-> Table "PUBLIC"."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 *** + {query_map[3070][0]} + {query_map[3070][1]} Sub-query (invariant) ....-> Filter ........-> Refetch ............-> Sort (record length: 28, key length: 8) ................-> Filter - ....................-> Table "TEST" as "X11" Full Scan + ....................-> Table "PUBLIC"."TEST" as "X11" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A11" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4000][0]} + {query_map[4000][1]} Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "X12" Full Scan + ................-> Table "PUBLIC"."TEST" as "X12" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A12" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4010][0]} + {query_map[4010][1]} Sub-query (invariant) ....-> Sort (record length: 28, key length: 8) ........-> Filter - ............-> Table "TEST" as "X13" Full Scan + ............-> Table "PUBLIC"."TEST" as "X13" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A13" Full Scan + ........-> Table "PUBLIC"."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. + {query_map[4020][0]} + {query_map[4020][1]} Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 36, key length: 12) ............-> Filter - ................-> Table "TEST" as "X14" Full Scan + ................-> Table "PUBLIC"."TEST" as "X14" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A14" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4030][0]} + {query_map[4030][1]} Sub-query (invariant) ....-> Sort (record length: 36, key length: 16) ........-> Filter - ............-> Table "TEST" as "X15" Full Scan + ............-> Table "PUBLIC"."TEST" as "X15" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A15" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4040][0]} + {query_map[4040][1]} Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 36, key length: 16) ............-> Filter - ................-> Table "TEST" as "X16" Full Scan + ................-> Table "PUBLIC"."TEST" as "X16" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A16" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4050][0]} + {query_map[4050][1]} Sub-query (invariant) ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "X17" Full Scan + ................-> Table "PUBLIC"."TEST" as "X17" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A17" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4060][0]} + {query_map[4060][1]} Sub-query (invariant) ....-> Sort (record length: 28, key length: 8) ........-> Filter - ............-> Table "TEST" as "X18" Full Scan + ............-> Table "PUBLIC"."TEST" as "X18" Full Scan Select Expression ....-> Filter (preliminary) - ........-> Table "TEST" as "A18" Full Scan + ........-> Table "PUBLIC"."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 + {query_map[4070][0]} + {query_map[4070][1]} Sub-query ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "R X" Full Scan + ................-> Table "PUBLIC"."TEST" as "R" "X" Full Scan Sub-query ....-> Refetch ........-> Sort (record length: 28, key length: 8) ............-> Filter - ................-> Table "TEST" as "R X" Full Scan + ................-> Table "PUBLIC"."TEST" as "R" "X" Full Scan Select Expression ....-> Recursion ........-> Filter - ............-> Table "TEST" as "R A19" Full Scan + ............-> Table "PUBLIC"."TEST" as "R" "A19" Full Scan ........-> Filter - ............-> Table "TEST" as "R I" Full Scan + ............-> Table "PUBLIC"."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 + {query_map[5000][0]} + {query_map[5000][1]} 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 + ................-> Table "PUBLIC"."TEST" as "V01" "PUBLIC"."TEST" Full Scan + ................-> Table "SYSTEM"."RDB$DATABASE" as "V01" "SYSTEM"."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) + {query_map[6000][0]} + {query_map[6000][1]} Select Expression ....-> Refetch ........-> Sort (record length: 28, key length: 8) - ............-> Table "TEST" as "A21" Full Scan + ............-> Table "PUBLIC"."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) + {query_map[6010][0]} + {query_map[6010][1]} Select Expression ....-> Sort (record length: 1036, key length: 8) - ........-> Table "TEST" as "A22" Full Scan + ........-> Table "PUBLIC"."TEST" as "A22" Full Scan 7000 - select * from test_ns_01 a23 order by id - MUST use refetch + {query_map[7000][0]} + {query_map[7000][1]} Select Expression ....-> Refetch ........-> Sort (record length: 44, key length: 24) - ............-> Table "TEST_NS_01" as "A23" Full Scan + ............-> Table "PUBLIC"."TEST_NS_01" as "A23" Full Scan 7010 - select * from test_ns_02 a24 order by id - Must NOT refetch + {query_map[7010][0]} + {query_map[7010][1]} Select Expression ....-> Sort (record length: 1052, key length: 24) - ........-> Table "TEST_NS_02" as "A24" Full Scan + ........-> Table "PUBLIC"."TEST_NS_02" as "A24" Full Scan 7020 - select * from test_ns_03 order by id - MUST use refetch + {query_map[7020][0]} + {query_map[7020][1]} Select Expression ....-> Refetch ........-> Sort (record length: 36, key length: 12) - ............-> Table "TEST_NS_03" Full Scan + ............-> Table "PUBLIC"."TEST_NS_03" Full Scan 7030 - select * from test_ns_04 order by id - Must NOT use refetch + {query_map[7030][0]} + {query_map[7030][1]} Select Expression ....-> Sort (record length: 1036, key length: 12) - ........-> Table "TEST_NS_04" Full Scan + ........-> Table "PUBLIC"."TEST_NS_04" Full Scan 7040 - select * from test_ns_05 order by id - MUST use refetch + {query_map[7040][0]} + {query_map[7040][1]} Select Expression ....-> Refetch ........-> Sort (record length: 36, key length: 12) - ............-> Table "TEST_NS_05" Full Scan + ............-> Table "PUBLIC"."TEST_NS_05" Full Scan 7050 - select * from test_ns_06 order by id - Must NOT use refetch + {query_map[7050][0]} + {query_map[7050][1]} Select Expression ....-> Sort (record length: 1036, key length: 12) - ........-> Table "TEST_NS_06" Full Scan + ........-> Table "PUBLIC"."TEST_NS_06" Full Scan """ act = python_act('db') From 47e31678c24bbab75c2c7d0a53241d16aac6a76a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:46:09 +0300 Subject: [PATCH 0723/1064] Added/Updated tests\bugs\core_2678_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2678_test.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2678_test.py b/tests/bugs/core_2678_test.py index 73d08c6d..f0364495 100644 --- a/tests/bugs/core_2678_test.py +++ b/tests/bugs/core_2678_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2678 FBTEST: bugs.core_2678 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -52,15 +58,19 @@ d1.c3, d2.c3; """ + act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN SORT (JOIN (JOIN (D2 NATURAL, D1 INDEX (IDX_TD_DATA1)), JOIN (D1 NATURAL, D2 INDEX (IDX_TD_DATA2)))) """ -@pytest.mark.version('>=3.0') +expected_stdout_6x = """ + PLAN SORT (JOIN (JOIN ("D2" NATURAL, "D1" INDEX ("PUBLIC"."IDX_TD_DATA1")), JOIN ("D1" NATURAL, "D2" INDEX ("PUBLIC"."IDX_TD_DATA2")))) +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From f4eb4fbebdffa5f3f82cd8ad4a52550466d09657 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 21:55:50 +0300 Subject: [PATCH 0724/1064] Added/Updated tests\bugs\core_2699_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2699_test.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_2699_test.py b/tests/bugs/core_2699_test.py index a741bbc5..8c8979cf 100644 --- a/tests/bugs/core_2699_test.py +++ b/tests/bugs/core_2699_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2699 FBTEST: bugs.core_2699 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,26 +21,33 @@ db_1 = db_factory() test_script = """ - with x as ( + with cte_alias as ( select 1 n from rdb$database ) - select * from x(10); + select * from cte_alias(10); """ act = isql_act('db_1', test_script, substitutions=[('-At line.*', '')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Dynamic SQL Error -SQL error code = -204 -Procedure unknown - -X + -CTE_ALIAS -At line 4, column 15 """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -204 + -Procedure unknown + -"CTE_ALIAS" +""" +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 618c84e962b12bc935d78236d633751b92129111 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 23:03:46 +0300 Subject: [PATCH 0725/1064] Added/Updated tests\bugs\core_2712_test.py: Re-implemented via try/except and check show exception data. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2712_test.py | 41 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_2712_test.py b/tests/bugs/core_2712_test.py index 75a20cae..f86a1f2e 100644 --- a/tests/bugs/core_2712_test.py +++ b/tests/bugs/core_2712_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2712 FBTEST: bugs.core_2712 +NOTES: + [26.06.2025] pzotov + Re-implemented via try/except and check show exception data. + Suppressing quotes around `id <...>` as irrelevant to this test. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,21 +21,32 @@ db = db_factory() -act = python_act('db', substitutions=[('table id [0-9]+ is not defined', 'table is not defined')]) +act = python_act('db', substitutions=[('table (")?id \\d+(")? is not defined', 'table is not defined')]) @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): - with act.db.connect() as att1: - cur1 = att1.cursor() + with act.db.connect() as con: + cur1 = con.cursor() cur1.execute("recreate table test(x int)") - att1.commit() + con.commit() cur1.execute("insert into test values(1)") - att1.commit() - with act.db.connect() as att2: - cur2 = att2.cursor() - cur2.execute("select 1 from rdb$database") - - cur1.execute("drop table test") - with pytest.raises(DatabaseError, match='.*table id [0-9]+ is not defined.*'): + con.commit() + try: + with act.db.connect() as con2: + cur2 = con2.cursor() + cur2.execute("select 1 from rdb$database") + cur1.execute("drop table test") cur2.prepare("update test set x=-x") - att2.commit() + con2.commit() + except Exception as e: + print(e.__str__()) + for x in e.gds_codes: + print(x) + + act.expected_stdout = """ + table is not defined + 335544395 + """ + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() From 1a330b8ac6e485ce47184bc6fafd00cc718093d9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 23:09:22 +0300 Subject: [PATCH 0726/1064] Added/Updated tests\bugs\core_2735_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2735_test.py | 47 ++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_2735_test.py b/tests/bugs/core_2735_test.py index 84cba4f0..7e301297 100644 --- a/tests/bugs/core_2735_test.py +++ b/tests/bugs/core_2735_test.py @@ -7,33 +7,50 @@ DESCRIPTION: JIRA: CORE-2735 FBTEST: bugs.core_2735 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """set term ^; -create procedure p returns(a int) as begin a = 9; suspend; end^ -create view vp1 as select a from p^ -set term ;^ -COMMIT;""" +init_script = """ + set term ^; + create procedure sp_test returns(o_result int) as begin o_result = 9; suspend; end^ + create view vp1 as select o_result from sp_test^ + set term ;^ + commit; +""" db = db_factory(charset='UTF8', init=init_script) -test_script = """show view vp1; +test_script = """ + show view vp1; """ -act = isql_act('db', test_script) +substitutions = [('==.*', ''), ('[ \t]+', ' ')] + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """A INTEGER Nullable -View Source: -==== ====== - select a from p +expected_stdout_5x = """ + O_RESULT INTEGER Nullable + View Source: + select o_result from sp_test """ -@pytest.mark.version('>=2.5.0') +expected_stdout_6x = """ + View: PUBLIC.VP1 + O_RESULT INTEGER Nullable + View Source: + select o_result from sp_test +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 08b6d695d09a485eb18c5c961bb799970b119576 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 23:12:06 +0300 Subject: [PATCH 0727/1064] Added/Updated tests\bugs\core_2741_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2741_test.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_2741_test.py b/tests/bugs/core_2741_test.py index 4a622855..ec590604 100644 --- a/tests/bugs/core_2741_test.py +++ b/tests/bugs/core_2741_test.py @@ -22,18 +22,26 @@ show domain dm_dts; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] -expected_stdout = """ - DM_INT INTEGER Nullable - cHeCk(vAlUE<>0) - DM_DTS TIMESTAMP Nullable - cHeCk(valUe<>cUrrent_timEstamp) +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + DM_INT INTEGER Nullable + cHeCk(vAlUE<>0) + DM_DTS TIMESTAMP Nullable + cHeCk(valUe<>cUrrent_timEstamp) +""" + +expected_stdout_6x = """ + PUBLIC.DM_INT INTEGER Nullable + cHeCk(vAlUE<>0) + PUBLIC.DM_DTS TIMESTAMP Nullable + cHeCk(valUe<>cUrrent_timEstamp) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 53f34973e7067ef24eff5f66546ca72a07818d5a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 23:19:34 +0300 Subject: [PATCH 0728/1064] Added/Updated tests\bugs\core_2765_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_2765_test.py | 102 ++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/tests/bugs/core_2765_test.py b/tests/bugs/core_2765_test.py index bfcc96a5..c095b322 100644 --- a/tests/bugs/core_2765_test.py +++ b/tests/bugs/core_2765_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2765 FBTEST: bugs.core_2765 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -111,6 +117,8 @@ def test_1(act_1: Action, user_admin: User, user_work1: User, user_work2: User): assert (act_1.clean_stderr == act_1.clean_expected_stderr and act_1.clean_stdout == act_1.clean_expected_stdout) +################################################################################# + # version: 4.0 test_script_2 = """ @@ -162,44 +170,62 @@ def test_1(act_1: Action, user_admin: User, user_work1: User, user_work2: User): act_2 = isql_act('db', test_script_2, substitutions=substitutions) -expected_stdout_2 = """ - WHO_AM_I TMP$C2765_ADMIN - WHAT_IS_MY_ROLE RDB$ADMIN - - WHO_AM_I TMP$C2765_WORKER1 - WHAT_IS_MY_ROLE NONE - ID 1 - X 1000 - - Records affected: 1 - Records affected: 1 - Records affected: 1 - Records affected: 1 - - WHO_AM_I TMP$C2765_ADMIN - WHAT_IS_MY_ROLE NONE - - WHO_AM_I TMP$C2765_WORKER2 - WHAT_IS_MY_ROLE NONE - -""" - -expected_stderr_2 = """ - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -GRANT failed - -no SELECT privilege with grant option on table/view TEST - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is TMP$C2765_WORKER2 -""" - - @pytest.mark.version('>=4.0') def test_2(act_2: Action, user_admin: User, user_work1: User, user_work2: User): - act_2.expected_stdout = expected_stdout_2 - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert (act_2.clean_stderr == act_2.clean_expected_stderr and - act_2.clean_stdout == act_2.clean_expected_stdout) + + expected_stdout_5x = f""" + WHO_AM_I {user_admin.name.upper()} + WHAT_IS_MY_ROLE RDB$ADMIN + WHO_AM_I {user_work1.name.upper()} + WHAT_IS_MY_ROLE NONE + ID 1 + X 1000 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + WHO_AM_I {user_admin.name.upper()} + WHAT_IS_MY_ROLE NONE + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no SELECT privilege with grant option on table/view TEST + + WHO_AM_I {user_work2.name.upper()} + WHAT_IS_MY_ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + -Effective user is {user_work2.name.upper()} + """ + + expected_stdout_6x = f""" + WHO_AM_I {user_admin.name.upper()} + WHAT_IS_MY_ROLE RDB$ADMIN + WHO_AM_I {user_work1.name.upper()} + WHAT_IS_MY_ROLE NONE + ID 1 + X 1000 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + WHO_AM_I {user_admin.name.upper()} + WHAT_IS_MY_ROLE NONE + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no SELECT privilege with grant option on table/view "PUBLIC"."TEST" + + WHO_AM_I {user_work2.name.upper()} + WHAT_IS_MY_ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE "PUBLIC"."TEST" + -Effective user is {user_work2.name.upper()} + """ + + act_2.expected_stdout = expected_stdout_5x if act_2.is_version('<6') else expected_stdout_6x + act_2.execute(combine_output = True) + assert act_2.clean_stdout == act_2.clean_expected_stdout From 94f7475f9c0bb314b213ae748016416a2335d0d7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 26 Jun 2025 23:22:14 +0300 Subject: [PATCH 0729/1064] Added/Updated tests\bugs\core_2798_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2798_test.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2798_test.py b/tests/bugs/core_2798_test.py index 916dc2d2..f4668c14 100644 --- a/tests/bugs/core_2798_test.py +++ b/tests/bugs/core_2798_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2798 FBTEST: bugs.core_2798 +NOTES: + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,13 +37,16 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN JOIN (V P1 NATURAL, V P2 NATURAL, V T1 NATURAL, V T2 NATURAL) +expected_stdout_5x = """ + PLAN JOIN (V P1 NATURAL, V P2 NATURAL, V T1 NATURAL, V T2 NATURAL) +""" + +expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."V" "PUBLIC"."P1" NATURAL, "PUBLIC"."V" "P2" NATURAL, "PUBLIC"."V" "PUBLIC"."T1" NATURAL, "PUBLIC"."V" "T2" NATURAL) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 501b41127c4cc811b318fd9be3665167dd57bc7c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 09:43:21 +0300 Subject: [PATCH 0730/1064] Added/Updated tests\bugs\core_2806_test.py: Reimplemented. No need to use 'SHOW VIEW' in this test. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2806_test.py | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_2806_test.py b/tests/bugs/core_2806_test.py index 1c43f3ea..7b1e7cf9 100644 --- a/tests/bugs/core_2806_test.py +++ b/tests/bugs/core_2806_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-2806 FBTEST: bugs.core_2806 +NOTES: + [27.06.2025] pzotov + Reimplemented. No need to use 'SHOW VIEW' in this test. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,24 +19,34 @@ db = db_factory(charset='UTF8') -test_script = """set term ^; -create procedure p returns(rc int) as begin rc = 1; suspend; end^ -create view v2(dosrc) as select rc * 2 from p^ -commit ^ -show view v2^ +VIEW_DDL = 'select rc * 2 from sp_test' +test_script = f""" + set list on; + set blob all; + set term ^; + create procedure sp_test returns(rc int) as + begin + rc = 1; + suspend; + end^ + set term ;^ + create view v_test(double_rc) as {VIEW_DDL}; + commit; + select r.rdb$view_source as blob_id from rdb$relations r where r.rdb$relation_name = upper('v_test'); + select * from v_test; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' '), ('BLOB_ID.*', '')] + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """DOSRC BIGINT Expression -View Source: -==== ====== - select rc * 2 from p +expected_stdout = f""" + {VIEW_DDL} + DOUBLE_RC 2 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 01ab40bc98d4b61ea4e541c9745b51632f6fa7b3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 09:54:15 +0300 Subject: [PATCH 0731/1064] Added/Updated tests\bugs\core_2812_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2812_test.py | 75 +++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_2812_test.py b/tests/bugs/core_2812_test.py index c1108c82..1f079129 100644 --- a/tests/bugs/core_2812_test.py +++ b/tests/bugs/core_2812_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2812 FBTEST: bugs.core_2812 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -36,8 +42,6 @@ recreate table test(x int); insert into test values(1); commit; - - """ db = db_factory(init=init_script) @@ -121,53 +125,80 @@ """ -act = isql_act('db', test_script, substitutions=[('=.*', ''), ('-At line.*', '')]) +substitutions = [('[ \t]+', ' '), ('-At line.*', '')] -expected_stdout = """ +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -L.ID + -At line 11, column 33 MSG case-2 A_ID 111 MID_ID 1 B_ID 111 VAL 0 - MSG case-2 A_ID 999 MID_ID 1 B_ID 999 VAL 123456789 - + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -A.ID + -At line 4, column 24 MSG case-4 ID 1 - Z1 1 - + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -S.X + -At line 11, column 29 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42S22 Dynamic SQL Error -SQL error code = -206 -Column unknown - -L.ID - + -"L"."ID" + -At line 11, column 33 + MSG case-2 + A_ID 111 + MID_ID 1 + B_ID 111 + VAL 0 + MSG case-2 + A_ID 999 + MID_ID 1 + B_ID 999 + VAL 123456789 Statement failed, SQLSTATE = 42S22 Dynamic SQL Error -SQL error code = -206 -Column unknown - -A.ID - + -"A"."ID" + -At line 5, column 24 + MSG case-4 + ID 1 + Z1 1 Statement failed, SQLSTATE = 42S22 Dynamic SQL Error - -SQL error code + -SQL error code = -206 -Column unknown - -S.X + -"S"."X" + -At line 12, column 29 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4dcd90e878e129f70e60afcef5e6e263bd8ac1c4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 09:57:32 +0300 Subject: [PATCH 0732/1064] Added/Updated tests\bugs\core_2826_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2826_test.py | 37 ++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_2826_test.py b/tests/bugs/core_2826_test.py index 6786ac8c..e1fa29e9 100644 --- a/tests/bugs/core_2826_test.py +++ b/tests/bugs/core_2826_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2826 FBTEST: bugs.core_2826 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,23 +57,34 @@ -- 'show table' was removed, see CORE-4782 ("Command `SHOW TABLE` fails..." - reproduced on Windows builds 2.5 and 3.0 only) """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' '), ('-At line.*', '')] + +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN (T1 NATURAL) - K1 ap - K2 123 + K1 ap + K2 123 K3 - PLAN (T1 INDEX (TXT1_NOPAD_PK)) - K1 ap - K2 123 + K1 ap + K2 123 + K3 +""" + +expected_stdout_6x = """ + PLAN ("T1" NATURAL) + K1 ap + K2 123 + K3 + PLAN ("T1" INDEX ("PUBLIC"."TXT1_NOPAD_PK")) + K1 ap + K2 123 K3 """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 223b2926666852478b28c3d9f13cecb1c26e3a90 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 10:04:01 +0300 Subject: [PATCH 0733/1064] Added/Updated tests\bugs\core_2835_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2835_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_2835_test.py b/tests/bugs/core_2835_test.py index 40fcefb5..da3afd46 100644 --- a/tests/bugs/core_2835_test.py +++ b/tests/bugs/core_2835_test.py @@ -7,12 +7,18 @@ DESCRIPTION: JIRA: CORE-2835 FBTEST: bugs.core_2835 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db_1 = db_factory() +db = db_factory() test_script = """ create table net_net_device( @@ -75,15 +81,19 @@ and t0_dep.id=t3_nd_dependantdevices_relation.secondary_devid; """ -act = isql_act('db_1', test_script) -expected_stdout = """ +act = isql_act('db', test_script) + +expected_stdout_5x = """ PLAN SORT (JOIN (T1_ND INDEX (PK_NET_NET_DEVICE), T3_ND_DEPENDANTDEVICES_RELATION INDEX (FK_NET_DEV_INTERCONNECTION_001), T0_DEP INDEX (PK_NET_NET_DEVICE))) """ +expected_stdout_6x = """ + PLAN SORT (JOIN ("T1_ND" INDEX ("PUBLIC"."PK_NET_NET_DEVICE"), "T3_ND_DEPENDANTDEVICES_RELATION" INDEX ("PUBLIC"."FK_NET_DEV_INTERCONNECTION_001"), "T0_DEP" INDEX ("PUBLIC"."PK_NET_NET_DEVICE"))) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 135c529aa9a658c2bc25816e904e520ab3d70f6f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 10:22:31 +0300 Subject: [PATCH 0734/1064] Added/Updated tests\bugs\core_2881_test.py: Re-implemented: use variables to store scema prefix (since 6.0.0.834), packages header and body. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2881_test.py | 160 +++++++++++++++++------------------ 1 file changed, 76 insertions(+), 84 deletions(-) diff --git a/tests/bugs/core_2881_test.py b/tests/bugs/core_2881_test.py index e071b53b..37ecb728 100644 --- a/tests/bugs/core_2881_test.py +++ b/tests/bugs/core_2881_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2881 FBTEST: bugs.core_2881 +NOTES: + [27.06.2025] pzotov + Re-implemented: use variables to store scema prefix (since 6.0.0.834), packages header and body. + Use f-notations to substitute variable values in the test script and expected_out. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,104 +20,90 @@ db = db_factory() -test_script = """ - set term ^; - create or alter package p1 - as - begin - function f(x int) returns int; - procedure p(x int) returns(y int); - end - ^ - create package body p1 - as - begin - function f(x int) returns int as +act = isql_act('db') + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + PKG_HEAD_1 = """ begin - return 22*x; + function f(x int) returns int; + procedure p(x int) returns(y int); end - procedure p(x int) returns(y int) as + """ + PKG_BODY_1 = """ begin - y = 33*x; - suspend; + function f(x int) returns int as + begin + return 22*x; + end + procedure p(x int) returns(y int) as + begin + y = 33*x; + suspend; + end end - end - ^ + """ - create or alter package p2 - as - begin - function f(x int) returns int; - procedure p(x int) returns(y int); - end - ^ - create package body p2 - as - begin - function f(x int) returns int as + PKG_HEAD_2 = """ begin - return 222*x; + function f(x int) returns int; + procedure p(x int) returns(y int); end - procedure p(x int) returns(y int) as + """ + PKG_BODY_2 = """ begin - y = 333*x; - suspend; + function f(x int) returns int as + begin + return 222*x; + end + procedure p(x int) returns(y int) as + begin + y = 333*x; + suspend; + end end - end - ^ - set term ;^ - commit; + """ - show package p1; - show package p2; -""" + test_script = f""" + set term ^; + ^ + create package p1 as + {PKG_HEAD_1} + ^ + create package body p1 as + {PKG_BODY_1} + ^ + create package p2 as + {PKG_HEAD_2} + ^ + create package body p2 as + {PKG_BODY_2} + ^ + set term ;^ + commit; -act = isql_act('db', test_script) + show package p1; + show package p2; + """ -expected_stdout = """ - P1 - Header source: - begin - function f(x int) returns int; - procedure p(x int) returns(y int); - end + expected_stdout = f""" + {SQL_SCHEMA_PREFIX}P1 + Header source: + {PKG_HEAD_1} - Body source: - begin - function f(x int) returns int as - begin - return 22*x; - end - procedure p(x int) returns(y int) as - begin - y = 33*x; - suspend; - end - end - P2 - Header source: - begin - function f(x int) returns int; - procedure p(x int) returns(y int); - end + Body source: + {PKG_BODY_1} - Body source: - begin - function f(x int) returns int as - begin - return 222*x; - end - procedure p(x int) returns(y int) as - begin - y = 333*x; - suspend; - end - end -""" + {SQL_SCHEMA_PREFIX}P2 + Header source: + {PKG_HEAD_2} + + Body source: + {PKG_BODY_2} + """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.isql(switches = ['-q'], input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 408aea8aed977646eb75b52200ed929d34c1c9f1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 10:42:13 +0300 Subject: [PATCH 0735/1064] Added/Updated tests\bugs\core_2910_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2910_test.py | 69 ++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/tests/bugs/core_2910_test.py b/tests/bugs/core_2910_test.py index 840e7393..f41ecbbc 100644 --- a/tests/bugs/core_2910_test.py +++ b/tests/bugs/core_2910_test.py @@ -7,46 +7,55 @@ DESCRIPTION: JIRA: CORE-2910 FBTEST: bugs.core_2910 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE R$TMP ( - POSTING_ID INTEGER -); - -CREATE TABLE TMP ( - POSTING_ID INTEGER NOT NULL -); - -ALTER TABLE TMP ADD CONSTRAINT PK_TMP PRIMARY KEY (POSTING_ID); -commit; -""" - -db = db_factory(charset='UTF8', init=init_script) - -test_script = """SET PLAN ON; -select r.POSTING_ID as r$POSTING_ID, t.POSTING_ID from ( - SELECT POSTING_ID - FROM r$tmp - ) r left join ( - select POSTING_ID from - (select - posting_id - from tmp) - ) t on r.POSTING_ID = t.POSTING_ID; +db = db_factory() + +test_script = """ + create table r$tmp ( + posting_id integer + ); + + create table tmp ( + posting_id integer not null + ); + + alter table tmp add constraint pk_tmp primary key (posting_id); + commit; + + set plan on; + select r.posting_id as r$posting_id, t.posting_id from ( + select posting_id + from r$tmp + ) r left join ( + select posting_id from + (select + posting_id + from tmp) + ) t on r.posting_id = t.posting_id; """ act = isql_act('db', test_script) -expected_stdout = """ -PLAN JOIN (R R$TMP NATURAL, T TMP INDEX (PK_TMP)) +expected_stdout_5x = """ + PLAN JOIN (R R$TMP NATURAL, T TMP INDEX (PK_TMP)) +""" + +expected_stdout_6x = """ + PLAN JOIN ("R" "PUBLIC"."R$TMP" NATURAL, "T" "PUBLIC"."TMP" INDEX ("PUBLIC"."PK_TMP")) """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 81552137ead8edfcd0d3402cf4c523462a9c41b8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 10:59:29 +0300 Subject: [PATCH 0736/1064] Added/Updated tests\bugs\core_2912_test.py: Removed 'set plan on' as irrelevant to this test. --- tests/bugs/core_2912_test.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_2912_test.py b/tests/bugs/core_2912_test.py index 314d0d95..d98db35d 100644 --- a/tests/bugs/core_2912_test.py +++ b/tests/bugs/core_2912_test.py @@ -11,8 +11,10 @@ [31.10.2024] pzotov Bug was fixed for too old FB (2.1.6; 2.5.3; 3.0 Alpha 1), firebird-driver and/or QA-plugin will not able to run on this version in order to reproduce problem. - Checked on 6.0.0.511 (Windows/Linux); 5.0.2.1551; 4.0.6.3165; 3.0.13.33794 + + [27.06.2025] pzotov + Removed 'set plan on' as irrelevant to this test. """ from pathlib import Path @@ -41,11 +43,7 @@ def test_1(act: Action, tmp_sql: Path): select c, upper(c) cu from test where c containing 'Faÿ'; select c, upper(c) cu from test where c starting with 'Faÿ'; select c, upper(c) cu from test where c like 'Faÿ%'; - -- ### ACHTUNG ### - -- As of WI-V2.5.4.26857, following will FAILS if character class "alpha" - -- will be specified not in UPPER case (see note in CORE-4740 08/Apr/15 05:48 PM): - select c, upper(c) cu from test where c similar to '[[:ALPHA:]]{1,}ÿ%'; - set plan on; + select c, upper(c) cu from test where c similar to '[[:alpha:]]{1,}ÿ%'; select c from test where upper (c collate iso8859_1) = upper('ÿ'); select c, upper(c) cu from test where upper (c collate iso8859_1) starting with upper('Faÿ'); """ @@ -67,9 +65,7 @@ def test_1(act: Action, tmp_sql: Path): CU FAÿ C Faÿ CU FAÿ - PLAN (TEST INDEX (TEST_CU)) C ÿ - PLAN (TEST INDEX (TEST_CU)) C Faÿ CU FAÿ """ From ed9a76454be0bec6ba4c8fbe606402eb04ed428a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 11:00:02 +0300 Subject: [PATCH 0737/1064] Added/Updated tests\bugs\core_2912_test.py: added marker --- tests/bugs/core_2912_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_2912_test.py b/tests/bugs/core_2912_test.py index d98db35d..2bd5882e 100644 --- a/tests/bugs/core_2912_test.py +++ b/tests/bugs/core_2912_test.py @@ -26,6 +26,7 @@ act = isql_act('db', substitutions=[('[ \\t]+', ' ')]) tmp_sql = temp_file('tmp_core_2912.sql') +@pytest.mark.intl @pytest.mark.version('>=3.0.0') def test_1(act: Action, tmp_sql: Path): From 9ff252dea259c46bbd603c4a4dde6de32fc4254c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 11:13:56 +0300 Subject: [PATCH 0738/1064] Added/Updated tests\bugs\core_2916_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2916_test.py | 82 ++++++++++++------------------------ 1 file changed, 28 insertions(+), 54 deletions(-) diff --git a/tests/bugs/core_2916_test.py b/tests/bugs/core_2916_test.py index f3bcf457..710cdc48 100644 --- a/tests/bugs/core_2916_test.py +++ b/tests/bugs/core_2916_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-2916 FBTEST: bugs.core_2916 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,70 +20,38 @@ # version: 3.0 -init_script_1 = """create table tab (col date); -insert into tab (col) values (current_date); -commit; -""" - -db_1 = db_factory(init=init_script_1) - -test_script_1 = """create index itab on tab computed (cast(col as int)); -commit; -select * from tab where cast(col as int) is null;""" - -act_1 = isql_act('db_1', test_script_1, - substitutions=[('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', '2011-05-03')]) - -expected_stdout_1 = """ - COL -=========== -""" - -expected_stderr_1 = """Statement failed, SQLSTATE = 22018 - -conversion error from string "2011-05-03" - -Statement failed, SQLSTATE = 22018 - -conversion error from string "2011-05-03" -""" - -@pytest.mark.version('>=3.0,<4.0') -def test_1(act_1: Action): - act_1.expected_stdout = expected_stdout_1 - act_1.expected_stderr = expected_stderr_1 - act_1.execute() - assert (act_1.clean_stderr == act_1.clean_expected_stderr and - act_1.clean_stdout == act_1.clean_expected_stdout) - -# version: 4.0 +db = db_factory() -db_2 = db_factory() - -test_script_2 = """ +test_script = """ recreate table tab (col date); - insert into tab (col) values ( date '29.02.2004' ); + insert into tab (col) values ( current_date ); commit; - create index itab on tab computed (cast(col as int)); commit; - set list on; - select * from tab where cast(col as int) is null; """ -act_2 = isql_act('db_2', test_script_2) +substitutions = [('(-)?conversion error from string.*', 'conversion error from string')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr_2 = """ +expected_stdout_3x = """ Statement failed, SQLSTATE = 22018 - Expression evaluation error for index "***unknown***" on table "TAB" - -conversion error from string "2004-02-29" + conversion error from string "2021-09-27" +""" + +expected_stdout_5x = """ Statement failed, SQLSTATE = 22018 - conversion error from string "2004-02-29" + Expression evaluation error for index "***unknown***" on table "TAB" + conversion error from string "2021-09-27" """ -@pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert act_2.clean_stderr == act_2.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 22018 + Expression evaluation error for index ""***unknown***"" on table ""PUBLIC"."TAB"" + conversion error from string "2021-09-27" +""" +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d4f5347451e4c2d9bab074fa818328a49dfba751 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 11:21:51 +0300 Subject: [PATCH 0739/1064] Added/Updated tests\bugs\core_2930_test.py: Removed 'SHOW' commands from test as they can be replaced with query to rdb$procedure_parameters. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2930_test.py | 54 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_2930_test.py b/tests/bugs/core_2930_test.py index ce3d32f3..ae994b3a 100644 --- a/tests/bugs/core_2930_test.py +++ b/tests/bugs/core_2930_test.py @@ -7,39 +7,45 @@ DESCRIPTION: JIRA: CORE-2930 FBTEST: bugs.core_2930 +NOTES: + [27.06.2025] pzotov + Removed 'SHOW' commands from test as they can be replaced with query to rdb$procedure_parameters. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """set term !; -create procedure p1 returns (n integer) as begin suspend; end! -create view v1 as select * from p1! -commit! -set term ;! -""" - -db = db_factory(charset='UTF8', init=init_script) - -test_script = """show procedure p1; -drop view v1; -show procedure p1; +db = db_factory() + +test_script = """ + set list on; + set term ^; + create procedure sp_test returns (o_result integer) as + begin + o_result = 1; + suspend; + end ^ + set term ;^ + create view v1 as select * from sp_test; + commit; + drop view v1; + select + pp.rdb$parameter_name + ,pp.rdb$parameter_number + ,pp.rdb$parameter_type + from rdb$procedure_parameters pp where pp.rdb$procedure_name = upper('sp_test'); + select * from sp_test; """ act = isql_act('db', test_script) -expected_stdout = """Procedure text: -============================================================================= - begin suspend; end -============================================================================= -Parameters: -N OUTPUT INTEGER -Procedure text: -============================================================================= - begin suspend; end -============================================================================= -Parameters: -N OUTPUT INTEGER +expected_stdout = """ + RDB$PARAMETER_NAME O_RESULT + RDB$PARAMETER_NUMBER 0 + RDB$PARAMETER_TYPE 1 + O_RESULT 1 """ @pytest.mark.version('>=3.0') From 315c020ba1b1799a09c1a07a1d0db953992dfa19 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 11:44:28 +0300 Subject: [PATCH 0740/1064] Added/Updated tests\bugs\core_2985_test.py: Replaced 'SHOW' command with query to 't_dependant'. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_2985_test.py | 42 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_2985_test.py b/tests/bugs/core_2985_test.py index b42f8674..ebafaddf 100644 --- a/tests/bugs/core_2985_test.py +++ b/tests/bugs/core_2985_test.py @@ -7,31 +7,39 @@ DESCRIPTION: JIRA: CORE-2985 FBTEST: bugs.core_2985 +NOTES: + [27.06.2025] pzotov + Replaced 'SHOW' command with query to 't_dependant'. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table test (id numeric, f1 varchar(20)); -create table test1(id1 numeric, ff computed((select f1 from test where id=id1))); -commit; -""" - -db = db_factory(init=init_script) - -test_script = """show table test1; -alter table test1 alter ff computed(cast(null as varchar(20))); -drop table test; -commit; -show table test1; +db = db_factory() + +test_script = """ + set list on; + create table t_source (id numeric, f1 varchar(20)); + create table t_dependant(id1 numeric, ff computed( (select s.f1 from t_source s where s.id = id1) ) ); + commit; + insert into t_dependant(id1) values(1); + commit; + alter table t_dependant alter ff computed(cast(null as varchar(20))); + drop table t_source; + commit; + set count on; + select * from t_dependant; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ID1 NUMERIC(9, 0) Nullable -FF Computed by: ((select f1 from test where id=id1)) -ID1 NUMERIC(9, 0) Nullable -FF Computed by: (cast(null as varchar(20))) +expected_stdout = """ + ID1 1 + FF + Records affected: 1 """ @pytest.mark.version('>=3.0') From 7f7173841d89b1256dd578559e09110121b2f98e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 13:32:01 +0300 Subject: [PATCH 0741/1064] Added/Updated tests\bugs\core_3029_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3029_test.py | 220 ++++++++++++++++++++--------------- 1 file changed, 126 insertions(+), 94 deletions(-) diff --git a/tests/bugs/core_3029_test.py b/tests/bugs/core_3029_test.py index 6a6bb087..ca5272e3 100644 --- a/tests/bugs/core_3029_test.py +++ b/tests/bugs/core_3029_test.py @@ -7,110 +7,142 @@ DESCRIPTION: JIRA: CORE-3029 FBTEST: bugs.core_3029 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create sequence test_gen; - -recreate table test_row -(id int not null, - did int not null, - pid int not null, - dep int not null -); -alter table test_row add constraint pk_test_row primary key(id); -create unique index ix_test_row1 on test_row(did, pid, dep); -commit; - -insert into test_row(id, did, pid,dep) values(1, 2, 3, 4); -commit; -""" - -db = db_factory(init=init_script) - -test_script = """set term !!; -execute block returns(id int, did int, dep int, pid int) -as -declare variable xid int; -begin - select id,did, pid,dep - from test_row - where id=(select min(id) from test_row) - into :xid, :did, pid, :dep; - - while (1=1) do - begin - delete from test_row r where r.id = :xid; - - insert into test_row(id, did, dep, pid) - values (gen_id(test_gen, 1), :did, :dep, :pid); - - suspend; - - when any do - exception; - end -end !! -rollback !! -create or alter procedure sp_test - returns(id int, did int, dep int, pid int) -as -declare variable xid int; -begin - select id,did, pid,dep - from test_row - where id=(select min(id) from test_row) - into :xid, :did, pid, :dep; - - while (1=1) do - begin - delete from test_row r where r.id = :xid; - - insert into test_row(id, did, dep, pid) - values (gen_id(test_gen, 1), :did, :dep, :pid); - - suspend; - - when any do - exception; - end -end !! -select * from sp_test !! -rollback !! +db = db_factory() + +test_script = """ + set list on; + create sequence test_gen; + recreate table test_row + (id int not null, + did int not null, + pid int not null, + dep int not null + ); + alter table test_row add constraint pk_test_row primary key(id); + create unique index ix_test_row1 on test_row(did, pid, dep); + commit; + + insert into test_row(id, did, pid,dep) values(1, 2, 3, 4); + commit; + + set term ^; + execute block returns(id int, did int, dep int, pid int) + as + declare variable xid int; + begin + select id,did, pid,dep + from test_row + where id=(select min(id) from test_row) + into :xid, :did, pid, :dep; + + while (1=1) do + begin + delete from test_row r where r.id = :xid; + + insert into test_row(id, did, dep, pid) + values (gen_id(test_gen, 1), :did, :dep, :pid); + + suspend; + + when any do + exception; + end + end ^ + rollback ^ + create or alter procedure sp_test + returns(id int, did int, dep int, pid int) + as + declare variable xid int; + begin + select id,did, pid,dep + from test_row + where id=(select min(id) from test_row) + into :xid, :did, pid, :dep; + + while (1=1) do + begin + delete from test_row r where r.id = :xid; + + insert into test_row(id, did, dep, pid) + values (gen_id(test_gen, 1), :did, :dep, :pid); + + suspend; + + when any do + exception; + end + end ^ + select * from sp_test ^ + rollback ^ """ -act = isql_act('db', test_script, substitutions=[('line.*', ''), ('col.*', '')]) - -expected_stdout = """ - ID DID DEP PID -============ ============ ============ ============ - 2 4 3 - 2 4 3 - - ID DID DEP PID -============ ============ ============ ============ - 2 4 3 +substitutions = [ ('[ \t]+', ' '), ('line.*', ''), ('col.*', '')] + +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + ID + DID 2 + DEP 4 + PID 3 + ID + DID 2 + DEP 4 + PID 3 + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "IX_TEST_ROW1" + -Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) + -At block + -At block + ID + DID 2 + DEP 4 + PID 3 + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "IX_TEST_ROW1" + -Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) + -At procedure 'SP_TEST' + -At procedure 'SP_TEST' """ -expected_stderr = """Statement failed, SQLSTATE = 23000 -attempt to store duplicate value (visible to active transactions) in unique index "IX_TEST_ROW1" --Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) --At block --At block -Statement failed, SQLSTATE = 23000 -attempt to store duplicate value (visible to active transactions) in unique index "IX_TEST_ROW1" --Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) --At procedure 'SP_TEST' line: 15, col: 5 --At procedure 'SP_TEST' line: 20, col: 12 +expected_stdout_6x = """ + ID + DID 2 + DEP 4 + PID 3 + ID + DID 2 + DEP 4 + PID 3 + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "PUBLIC"."IX_TEST_ROW1" + -Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) + -At block + -At block + ID + DID 2 + DEP 4 + PID 3 + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "PUBLIC"."IX_TEST_ROW1" + -Problematic key value is ("DID" = 2, "PID" = 3, "DEP" = 4) + -At procedure "PUBLIC"."SP_TEST" + -At procedure "PUBLIC"."SP_TEST" """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f748104b4258e2e1d6a7dec35dbe786c8364925b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 13:35:14 +0300 Subject: [PATCH 0742/1064] Added/Updated tests\bugs\core_3055_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3055_test.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_3055_test.py b/tests/bugs/core_3055_test.py index 8e6dc606..54fe9304 100644 --- a/tests/bugs/core_3055_test.py +++ b/tests/bugs/core_3055_test.py @@ -3,11 +3,16 @@ """ ID: issue-3435 ISSUE: 3435 -TITLE: Variable/argument name could be absent or be wrong in error messages when more - than 256 variables are used +TITLE: Variable/argument name could be absent or be wrong in error messages when more than 256 variables are used DESCRIPTION: JIRA: CORE-3055 FBTEST: bugs.core_3055 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -2033,15 +2038,20 @@ act = isql_act('db', test_script, substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 validation error for variable V_NN, value "*** null ***" - -At block line: 2004, col: 9 + -At block line """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + validation error for variable "V_NN", value "*** null ***" + -At block line +""" +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From da1b0769af1f84b65e1e50c067989db293b57be5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 13:47:25 +0300 Subject: [PATCH 0743/1064] Added/Updated tests\bugs\core_3056_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3056_test.py | 469 ++++++++++++++++++++--------------- 1 file changed, 271 insertions(+), 198 deletions(-) diff --git a/tests/bugs/core_3056_test.py b/tests/bugs/core_3056_test.py index 174f8cd4..6f36197b 100644 --- a/tests/bugs/core_3056_test.py +++ b/tests/bugs/core_3056_test.py @@ -3,11 +3,19 @@ """ ID: issue-3436 ISSUE: 3436 -TITLE: Problems may happen when issuing DDL commands in the same transaction after - CREATE COLLATION was issued +TITLE: Problems may happen when issuing DDL commands in the same transaction after CREATE COLLATION was issued DESCRIPTION: JIRA: CORE-3056 FBTEST: bugs.core_3056 +NOTES: + [27.06.2025] pzotov + Uncommented lines "--,constraint test_pk1 primary key" and added "alter table drop constraint " + because core-4783 has been fixed long ago. + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,14 +24,6 @@ db = db_factory() test_script = """ - -- NOTES. - -- 1. Results are identical on: LI-T3.0.0.31827 (64 bit) and WI-T3.0.0.31827 (32 bit). - -- 2. Despite of ticket issue that it was fixed only in 3.0, following script works OK on also oon 2.5 - -- (tested on WI-V2.5.5.26861; differences are only in stderr). - -- 3. ## TODO ### - -- Uncomment lines "--,constraint test_pk1 primary key" after CORE-4783 will be fixed, and add - -- statement 'alter table drop constraint " before each DROP TABLE statements. - create or alter view v_test_fields_ddl as select rf.rdb$field_name fld_name @@ -36,18 +36,6 @@ where rf.rdb$relation_name = 'TEST' order by rf.rdb$field_position; - /* - -- This works only in 3.0 and does NOT in 2.5 (rdb$collation_id present there only in rdb$relation_fields and NOT in rdb$fields): - create or alter view v_test_fields_ddl as - select rf.rdb$field_name fld_name, cs.rdb$character_set_name cset_name, co.rdb$base_collation_name base_coll, co.rdb$collation_attributes - from rdb$relation_fields rf - join rdb$fields ff on rf.rdb$field_source = ff.rdb$field_name - join rdb$character_sets cs on ff.rdb$character_set_id = cs.rdb$character_set_id - join rdb$collations co on ff.rdb$collation_id = co.rdb$collation_id - where rf.rdb$relation_name = 'TEST' - order by rf.rdb$field_position; - */ - recreate table test(id int); commit; set term ^; @@ -128,11 +116,14 @@ ,f10 varchar(2) character set win1251 collate coll_10 ,f11 varchar(2) character set win1251 collate coll_11 ,f12 varchar(2) character set win1251 collate coll_12 - --,constraint test_pk1 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) + -- 27.06.2025: uncommented PK because core-4783 ( https://github.com/FirebirdSQL/firebird/issues/5082 ) + -- has been fixed in 3.0.8 / 4.0.1 / 5.0 Beta1: + ,constraint test_pk1 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) ); select * from v_test_fields_ddl; + alter table test drop constraint test_pk1; drop table test; drop collation coll_01; @@ -174,10 +165,13 @@ ,f10 varchar(2) character set utf8 collate coll_10 ,f11 varchar(2) character set utf8 collate coll_11 ,f12 varchar(2) character set utf8 collate coll_12 - --,constraint test_pk2 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) + -- 27.06.2025: uncommented PK because core-4783 ( https://github.com/FirebirdSQL/firebird/issues/5082 ) + -- has been fixed in 3.0.8 / 4.0.1 / 5.0 Beta1: + ,constraint test_pk2 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) ); select * from v_test_fields_ddl; + alter table test drop constraint test_pk2; drop table test; drop collation coll_01; @@ -221,7 +215,9 @@ ,f10 varchar(2) character set iso8859_1 collate coll_10 ,f11 varchar(2) character set iso8859_1 collate coll_11 ,f12 varchar(2) character set iso8859_1 collate coll_12 - --,constraint test_pk2 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) + -- 27.06.2025: uncommented PK because core-4783 ( https://github.com/FirebirdSQL/firebird/issues/5082 ) + -- has been fixed in 3.0.8 / 4.0.1 / 5.0 Beta1: + ,constraint test_pk2 primary key (f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12) ); select * from v_test_fields_ddl; @@ -237,181 +233,258 @@ act = isql_act('db', test_script) -expected_stdout = """ - select * from v_test_fields_ddl; - Records affected: 0 - drop collation coll_01; - set echo off; - - FLD_NAME F01 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F02 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F03 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F04 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F05 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F06 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F07 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F08 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F09 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F10 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F11 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - FLD_NAME F12 - CSET_NAME WIN1251 - BASE_COLL PXW_CYRL - - - - FLD_NAME F01 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F02 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F03 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F04 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F05 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F06 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F07 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F08 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F09 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F10 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F11 - CSET_NAME UTF8 - BASE_COLL UNICODE - - FLD_NAME F12 - CSET_NAME UTF8 - BASE_COLL UNICODE - - - - FLD_NAME F01 - CSET_NAME ISO8859_1 - BASE_COLL DA_DA - - FLD_NAME F02 - CSET_NAME ISO8859_1 - BASE_COLL DE_DE - - FLD_NAME F03 - CSET_NAME ISO8859_1 - BASE_COLL DU_NL - - FLD_NAME F04 - CSET_NAME ISO8859_1 - BASE_COLL EN_UK - - FLD_NAME F05 - CSET_NAME ISO8859_1 - BASE_COLL EN_US - - FLD_NAME F06 - CSET_NAME ISO8859_1 - BASE_COLL ES_ES - - FLD_NAME F07 - CSET_NAME ISO8859_1 - BASE_COLL ES_ES_CI_AI - - FLD_NAME F08 - CSET_NAME ISO8859_1 - BASE_COLL FI_FI - - FLD_NAME F09 - CSET_NAME ISO8859_1 - BASE_COLL FR_CA - - FLD_NAME F10 - CSET_NAME ISO8859_1 - BASE_COLL FR_FR - - FLD_NAME F11 - CSET_NAME ISO8859_1 - BASE_COLL IS_IS - - FLD_NAME F12 - CSET_NAME ISO8859_1 - BASE_COLL IT_IT - - - select * from v_test_fields_ddl; - Records affected: 0 - select * from rdb$collations co where co.rdb$collation_name starting with 'COLL_'; - Records affected: 0 +expected_stdout_5x = """ + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE TABLE TEST failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION COLL_01 for CHARACTER SET NONE is not defined + select * from v_test_fields_ddl; + Records affected: 0 + drop collation coll_01; + set echo off; + FLD_NAME F01 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F02 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F03 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F04 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F05 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F06 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F07 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F08 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F09 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F10 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F11 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F12 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F01 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F02 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F03 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F04 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F05 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F06 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F07 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F08 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F09 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F10 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F11 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F12 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F01 + CSET_NAME ISO8859_1 + BASE_COLL DA_DA + FLD_NAME F02 + CSET_NAME ISO8859_1 + BASE_COLL DE_DE + FLD_NAME F03 + CSET_NAME ISO8859_1 + BASE_COLL DU_NL + FLD_NAME F04 + CSET_NAME ISO8859_1 + BASE_COLL EN_UK + FLD_NAME F05 + CSET_NAME ISO8859_1 + BASE_COLL EN_US + FLD_NAME F06 + CSET_NAME ISO8859_1 + BASE_COLL ES_ES + FLD_NAME F07 + CSET_NAME ISO8859_1 + BASE_COLL ES_ES_CI_AI + FLD_NAME F08 + CSET_NAME ISO8859_1 + BASE_COLL FI_FI + FLD_NAME F09 + CSET_NAME ISO8859_1 + BASE_COLL FR_CA + FLD_NAME F10 + CSET_NAME ISO8859_1 + BASE_COLL FR_FR + FLD_NAME F11 + CSET_NAME ISO8859_1 + BASE_COLL IS_IS + FLD_NAME F12 + CSET_NAME ISO8859_1 + BASE_COLL IT_IT + select * from v_test_fields_ddl; + Records affected: 0 + select * from rdb$collations co where co.rdb$collation_name starting with 'COLL_'; + Records affected: 0 """ -expected_stderr = """ - Statement failed, SQLSTATE = 22021 - unsuccessful metadata update - -CREATE TABLE TEST failed - -Dynamic SQL Error - -SQL error code = -204 - -COLLATION COLL_01 for CHARACTER SET NONE is not defined +expected_stdout_6x = """ + Statement failed, SQLSTATE = 22021 + unsuccessful metadata update + -CREATE TABLE "PUBLIC"."TEST" failed + -Dynamic SQL Error + -SQL error code = -204 + -COLLATION "PUBLIC"."COLL_01" for CHARACTER SET "SYSTEM"."NONE" is not defined + select * from v_test_fields_ddl; + Records affected: 0 + drop collation coll_01; + set echo off; + FLD_NAME F01 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F02 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F03 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F04 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F05 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F06 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F07 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F08 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F09 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F10 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F11 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F12 + CSET_NAME WIN1251 + BASE_COLL PXW_CYRL + FLD_NAME F01 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F02 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F03 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F04 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F05 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F06 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F07 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F08 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F09 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F10 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F11 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F12 + CSET_NAME UTF8 + BASE_COLL UNICODE + FLD_NAME F01 + CSET_NAME ISO8859_1 + BASE_COLL DA_DA + FLD_NAME F02 + CSET_NAME ISO8859_1 + BASE_COLL DE_DE + FLD_NAME F03 + CSET_NAME ISO8859_1 + BASE_COLL DU_NL + FLD_NAME F04 + CSET_NAME ISO8859_1 + BASE_COLL EN_UK + FLD_NAME F05 + CSET_NAME ISO8859_1 + BASE_COLL EN_US + FLD_NAME F06 + CSET_NAME ISO8859_1 + BASE_COLL ES_ES + FLD_NAME F07 + CSET_NAME ISO8859_1 + BASE_COLL ES_ES_CI_AI + FLD_NAME F08 + CSET_NAME ISO8859_1 + BASE_COLL FI_FI + FLD_NAME F09 + CSET_NAME ISO8859_1 + BASE_COLL FR_CA + FLD_NAME F10 + CSET_NAME ISO8859_1 + BASE_COLL FR_FR + FLD_NAME F11 + CSET_NAME ISO8859_1 + BASE_COLL IS_IS + FLD_NAME F12 + CSET_NAME ISO8859_1 + BASE_COLL IT_IT + select * from v_test_fields_ddl; + Records affected: 0 + select * from rdb$collations co where co.rdb$collation_name starting with 'COLL_'; + Records affected: 0 """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 41528e12ea0f7e53c0c1ab344f91a6541dc707a8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 13:53:03 +0300 Subject: [PATCH 0744/1064] Added/Updated tests\bugs\core_3064_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3064_test.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_3064_test.py b/tests/bugs/core_3064_test.py index bb59d940..cbbe76b4 100644 --- a/tests/bugs/core_3064_test.py +++ b/tests/bugs/core_3064_test.py @@ -10,12 +10,20 @@ NOTES: [04.03.2023] pzotov Expected output was splitted because FB 5.x now *allows* execution w/o error. + + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ set term ^ ; create or alter procedure get_dates ( adate_from date, @@ -26,7 +34,7 @@ declare variable d date; begin d = adate_from; - while (d<=adate_to) do + while (d <= adate_to) do begin out_date = d; suspend; @@ -35,11 +43,7 @@ end^ set term ; ^ commit; -""" -db = db_factory(init=init_script) - -test_script = """ set planonly; select * from get_dates( 'yesterday', 'today' ) PLAN (GET_DATES NATURAL); select * from get_dates( 'yesterday', 'today' ) p PLAN (P NATURAL); @@ -47,7 +51,7 @@ act = isql_act('db', test_script, substitutions=[('offset .*', 'offset')]) -fb3x_expected_out = """ +expected_out_4x = """ Statement failed, SQLSTATE = 42S02 Dynamic SQL Error -SQL error code = -104 @@ -59,13 +63,18 @@ -BLR syntax error: expected TABLE at offset 51, encountered 132 """ -fb5x_expected_out = """ +expected_out_5x = """ PLAN (GET_DATES NATURAL) PLAN (P NATURAL) """ +expected_out_6x = """ + PLAN ("PUBLIC"."GET_DATES" NATURAL) + PLAN ("P" NATURAL) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = fb3x_expected_out if act.is_version('<5') else fb5x_expected_out + act.expected_stdout = expected_out_4x if act.is_version('<5') else expected_out_5x if act.is_version('<6') else expected_out_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From e409711e431e5d613241048084d2d80752a19b70 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:21:31 +0300 Subject: [PATCH 0745/1064] Added/Updated tests\bugs\core_3085_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3085_test.py | 69 +++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/tests/bugs/core_3085_test.py b/tests/bugs/core_3085_test.py index add533f4..05142b0d 100644 --- a/tests/bugs/core_3085_test.py +++ b/tests/bugs/core_3085_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3085 FBTEST: bugs.core_3085 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -17,22 +23,22 @@ test_script = """ create domain dm_int int; commit; - create table t(x dm_int); + create table test(x dm_int); commit; set term ^; - create procedure p(a dm_int) returns(msg varchar(30)) as + create procedure sp_test(a dm_int) returns(msg varchar(30)) as begin - msg='intro proc p: a=' || coalesce(a, 'null'); + msg='intro proc sp_test: a=' || coalesce(a, 'null'); suspend; end ^ set term ;^ commit; - insert into t values(1); - insert into t values(2); - insert into t values(3); + insert into test values(1); + insert into test values(2); + insert into test values(3); commit; set list on; @@ -40,43 +46,56 @@ alter domain dm_int set not null; commit; - select msg from p(null); - update t set x=null where x=2; + select msg from sp_test(null); + update test set x=null where x=2; commit; alter domain dm_int drop not null; commit; - select msg from p(null); - update t set x=null where x=2 returning x; + select msg from sp_test(null); + update test set x=null where x=2 returning x; commit; alter domain dm_int set not null; """ -act = isql_act('db', test_script) +substitutions = [] # [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) + -expected_stdout = """ - MSG intro proc p: a=null +expected_out_5x = """ + Statement failed, SQLSTATE = 42000 + validation error for variable A, value "*** null ***" + -At procedure 'SP_TEST' + + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."X", value "*** null ***" + MSG intro proc sp_test: a=null X + + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field X of table TEST NOT NULL because there are NULLs present """ -expected_stderr = """ +expected_out_6x = """ Statement failed, SQLSTATE = 42000 - validation error for variable A, value "*** null ***" - -At procedure 'P' + validation error for variable "A", value "*** null ***" + -At procedure "PUBLIC"."SP_TEST" + Statement failed, SQLSTATE = 23000 - validation error for column "T"."X", value "*** null ***" + validation error for column "PUBLIC"."TEST"."X", value "*** null ***" + MSG intro proc sp_test: a=null + X + Statement failed, SQLSTATE = 22006 unsuccessful metadata update - -Cannot make field X of table T NOT NULL because there are NULLs present + -Cannot make field "X" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0fe738a85d3aadd2b1794ebbe322a375a090d199 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:24:11 +0300 Subject: [PATCH 0746/1064] Added/Updated tests\bugs\core_3085_test.py: minor change: added subst --- tests/bugs/core_3085_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_3085_test.py b/tests/bugs/core_3085_test.py index 05142b0d..c6046701 100644 --- a/tests/bugs/core_3085_test.py +++ b/tests/bugs/core_3085_test.py @@ -60,7 +60,7 @@ alter domain dm_int set not null; """ -substitutions = [] # [ ('[ \t]+', ' ') ] +substitutions = [ ('[ \t]+', ' ') ] act = isql_act('db', test_script, substitutions = substitutions) From a92050c99020df318176b8410f80192248163ccd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:26:00 +0300 Subject: [PATCH 0747/1064] Added/Updated tests\bugs\core_3101_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3101_test.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_3101_test.py b/tests/bugs/core_3101_test.py index 9323f44d..d6327856 100644 --- a/tests/bugs/core_3101_test.py +++ b/tests/bugs/core_3101_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3101 FBTEST: bugs.core_3101 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -21,17 +27,23 @@ show domain state; """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_out_5x = """ + STATE SMALLINT Nullable + STATE SMALLINT Nullable + default 0 +""" -expected_stdout = """ - STATE SMALLINT Nullable - STATE SMALLINT Nullable - default 0 +expected_out_6x = """ + PUBLIC.STATE SMALLINT Nullable + PUBLIC.STATE SMALLINT Nullable + default 0 """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From c912251099a0a023c4883ef6924efc25eac94ee6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:27:55 +0300 Subject: [PATCH 0748/1064] Added/Updated tests\bugs\core_3103_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3103_test.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3103_test.py b/tests/bugs/core_3103_test.py index bdb8c564..7522d9c7 100644 --- a/tests/bugs/core_3103_test.py +++ b/tests/bugs/core_3103_test.py @@ -8,6 +8,12 @@ Ticket subj: Select statement with more non indexed reads in version 2.5RC3 as in version 2.1.3 JIRA: CORE-3103 FBTEST: bugs.core_3103 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -81,14 +87,18 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_out_5x = """ PLAN JOIN (A INDEX (BSTAMMDATEN_MASKENKEY), B INDEX (FK_BAUF_BSTAMMDATEN_ID)) PLAN (BAUF INDEX (BAUF_PK)) """ +expected_out_6x = """ + PLAN JOIN ("A" INDEX ("PUBLIC"."BSTAMMDATEN_MASKENKEY"), "B" INDEX ("PUBLIC"."FK_BAUF_BSTAMMDATEN_ID")) + PLAN ("PUBLIC"."BAUF" INDEX ("PUBLIC"."BAUF_PK")) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 2312aba532b93151ea706c7b26f11978f4b8bce5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:30:55 +0300 Subject: [PATCH 0749/1064] Added/Updated tests\bugs\core_3174_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3174_test.py | 348 ++++++++++++++++++++++++----------- 1 file changed, 239 insertions(+), 109 deletions(-) diff --git a/tests/bugs/core_3174_test.py b/tests/bugs/core_3174_test.py index b1f1b6b0..f107be3f 100644 --- a/tests/bugs/core_3174_test.py +++ b/tests/bugs/core_3174_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3174 FBTEST: bugs.core_3174 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -35,6 +41,7 @@ test_script = """ set plan on; + set list on; --set echo on; select '1.a' as test_no, id,'.' || c_pad || '.' as c_pad from t where trim(c_pad) = '123'; @@ -54,117 +61,240 @@ select '2.g' as test_no, id,'.' || c_nopad || '.' as c_nopad from t where trim(leading from c_nopad) starting with '123'; """ -act = isql_act('db', test_script, substitutions=[('=.*', '')]) - -expected_stdout = """ - PLAN (T NATURAL) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.a 1 .123. - 1.a 2 . 123. - 1.a 3 .123 . - 1.a 4 . 123 . - - - PLAN (T NATURAL) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.b 1 .123. - 1.b 3 .123 . - - - PLAN (T INDEX (T_C_PAD_TRIM_RIGHT)) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.c 1 .123. - 1.c 3 .123 . - - - PLAN (T INDEX (T_C_PAD_TRIM_LEFT)) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.d 1 .123. - 1.d 2 . 123. - 1.d 3 .123 . - 1.d 4 . 123 . - - - PLAN (T INDEX (T_C_PAD_TRIM_RIGHT)) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.e 1 .123. - 1.e 3 .123 . - - - PLAN (T INDEX (T_C_PAD_TRIM_LEFT)) - - TEST_NO ID C_PAD - ======= ============ ============ - 1.f 1 .123. - 1.f 2 . 123. - 1.f 3 .123 . - 1.f 4 . 123 . - - - PLAN (T NATURAL) - - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.a 1 .123. - 2.a 2 . 123. - 2.a 3 .123 . - 2.a 4 . 123 . - - - PLAN (T NATURAL) - - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.b 1 .123. - - - PLAN (T INDEX (T_C_NOPAD_TRIM_RIGHT)) - - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.c 1 .123. - 2.c 3 .123 . - - - PLAN (T INDEX (T_C_NOPAD_TRIM_LEFT)) - - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.d 1 .123. - 2.d 2 . 123. - - - PLAN (T INDEX (T_C_NOPAD_TRIM_RIGHT)) - - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.f 1 .123. - 2.f 3 .123 . - - - PLAN (T INDEX (T_C_NOPAD_TRIM_LEFT)) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) + + +expected_out_5x = """ + PLAN (T NATURAL) + TEST_NO 1.a + ID 1 + C_PAD .123. + TEST_NO 1.a + ID 2 + C_PAD . 123. + TEST_NO 1.a + ID 3 + C_PAD .123 . + TEST_NO 1.a + ID 4 + C_PAD . 123 . + PLAN (T NATURAL) + TEST_NO 1.b + ID 1 + C_PAD .123. + TEST_NO 1.b + ID 3 + C_PAD .123 . + PLAN (T INDEX (T_C_PAD_TRIM_RIGHT)) + TEST_NO 1.c + ID 1 + C_PAD .123. + TEST_NO 1.c + ID 3 + C_PAD .123 . + PLAN (T INDEX (T_C_PAD_TRIM_LEFT)) + TEST_NO 1.d + ID 1 + C_PAD .123. + TEST_NO 1.d + ID 2 + C_PAD . 123. + TEST_NO 1.d + ID 3 + C_PAD .123 . + TEST_NO 1.d + ID 4 + C_PAD . 123 . + PLAN (T INDEX (T_C_PAD_TRIM_RIGHT)) + TEST_NO 1.e + ID 1 + C_PAD .123. + TEST_NO 1.e + ID 3 + C_PAD .123 . + PLAN (T INDEX (T_C_PAD_TRIM_LEFT)) + TEST_NO 1.f + ID 1 + C_PAD .123. + TEST_NO 1.f + ID 2 + C_PAD . 123. + TEST_NO 1.f + ID 3 + C_PAD .123 . + TEST_NO 1.f + ID 4 + C_PAD . 123 . + PLAN (T NATURAL) + TEST_NO 2.a + ID 1 + C_NOPAD .123. + TEST_NO 2.a + ID 2 + C_NOPAD . 123. + TEST_NO 2.a + ID 3 + C_NOPAD .123 . + TEST_NO 2.a + ID 4 + C_NOPAD . 123 . + PLAN (T NATURAL) + TEST_NO 2.b + ID 1 + C_NOPAD .123. + PLAN (T INDEX (T_C_NOPAD_TRIM_RIGHT)) + TEST_NO 2.c + ID 1 + C_NOPAD .123. + TEST_NO 2.c + ID 3 + C_NOPAD .123 . + PLAN (T INDEX (T_C_NOPAD_TRIM_LEFT)) + TEST_NO 2.d + ID 1 + C_NOPAD .123. + TEST_NO 2.d + ID 2 + C_NOPAD . 123. + PLAN (T INDEX (T_C_NOPAD_TRIM_RIGHT)) + TEST_NO 2.f + ID 1 + C_NOPAD .123. + TEST_NO 2.f + ID 3 + C_NOPAD .123 . + PLAN (T INDEX (T_C_NOPAD_TRIM_LEFT)) + TEST_NO 2.g + ID 1 + C_NOPAD .123. + TEST_NO 2.g + ID 2 + C_NOPAD . 123. + TEST_NO 2.g + ID 3 + C_NOPAD .123 . + TEST_NO 2.g + ID 4 + C_NOPAD . 123 . +""" - TEST_NO ID C_NOPAD - ======= ============ ================================================ - 2.g 1 .123. - 2.g 2 . 123. - 2.g 3 .123 . - 2.g 4 . 123 . +expected_out_6x = """ + PLAN ("PUBLIC"."T" NATURAL) + TEST_NO 1.a + ID 1 + C_PAD .123. + TEST_NO 1.a + ID 2 + C_PAD . 123. + TEST_NO 1.a + ID 3 + C_PAD .123 . + TEST_NO 1.a + ID 4 + C_PAD . 123 . + PLAN ("PUBLIC"."T" NATURAL) + TEST_NO 1.b + ID 1 + C_PAD .123. + TEST_NO 1.b + ID 3 + C_PAD .123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_PAD_TRIM_RIGHT")) + TEST_NO 1.c + ID 1 + C_PAD .123. + TEST_NO 1.c + ID 3 + C_PAD .123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_PAD_TRIM_LEFT")) + TEST_NO 1.d + ID 1 + C_PAD .123. + TEST_NO 1.d + ID 2 + C_PAD . 123. + TEST_NO 1.d + ID 3 + C_PAD .123 . + TEST_NO 1.d + ID 4 + C_PAD . 123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_PAD_TRIM_RIGHT")) + TEST_NO 1.e + ID 1 + C_PAD .123. + TEST_NO 1.e + ID 3 + C_PAD .123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_PAD_TRIM_LEFT")) + TEST_NO 1.f + ID 1 + C_PAD .123. + TEST_NO 1.f + ID 2 + C_PAD . 123. + TEST_NO 1.f + ID 3 + C_PAD .123 . + TEST_NO 1.f + ID 4 + C_PAD . 123 . + PLAN ("PUBLIC"."T" NATURAL) + TEST_NO 2.a + ID 1 + C_NOPAD .123. + TEST_NO 2.a + ID 2 + C_NOPAD . 123. + TEST_NO 2.a + ID 3 + C_NOPAD .123 . + TEST_NO 2.a + ID 4 + C_NOPAD . 123 . + PLAN ("PUBLIC"."T" NATURAL) + TEST_NO 2.b + ID 1 + C_NOPAD .123. + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_NOPAD_TRIM_RIGHT")) + TEST_NO 2.c + ID 1 + C_NOPAD .123. + TEST_NO 2.c + ID 3 + C_NOPAD .123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_NOPAD_TRIM_LEFT")) + TEST_NO 2.d + ID 1 + C_NOPAD .123. + TEST_NO 2.d + ID 2 + C_NOPAD . 123. + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_NOPAD_TRIM_RIGHT")) + TEST_NO 2.f + ID 1 + C_NOPAD .123. + TEST_NO 2.f + ID 3 + C_NOPAD .123 . + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_C_NOPAD_TRIM_LEFT")) + TEST_NO 2.g + ID 1 + C_NOPAD .123. + TEST_NO 2.g + ID 2 + C_NOPAD . 123. + TEST_NO 2.g + ID 3 + C_NOPAD .123 . + TEST_NO 2.g + ID 4 + C_NOPAD . 123 . """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 189e90aeeb9ceb66fb27bfad2cb90381d321b56f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 14:38:33 +0300 Subject: [PATCH 0750/1064] Added/Updated tests\bugs\core_3180_test.py: Suppressed name of altered view in order to have same expected* text for versions prior/since 6.x Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3180_test.py | 48 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_3180_test.py b/tests/bugs/core_3180_test.py index 7d62839a..653a93ad 100644 --- a/tests/bugs/core_3180_test.py +++ b/tests/bugs/core_3180_test.py @@ -3,46 +3,42 @@ """ ID: issue-3554 ISSUE: 3554 -TITLE: ALTER VIEW with not matched columns in declaration and selection crashs the server +TITLE: ALTER VIEW with not matched columns in declaration and selection crashes the server DESCRIPTION: JIRA: CORE-3180 FBTEST: bugs.core_3180 +NOTES: + [27.06.2025] pzotov + Suppressed name of altered view in order to have same expected* text for versions prior/since 6.x + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create view TEST_VIEW (ID) as select 1 from rdb$database; -commit;""" - -db = db_factory(init=init_script) +db = db_factory() -test_script = """alter view TEST_VIEW (ID) as select 1, 2 from rdb$database; -COMMIT; -SHOW VIEW TEST_VIEW; +test_script = """ + create view TEST_VIEW (ID) as select 1 from rdb$database; + alter view TEST_VIEW (ID) as select 1, 2 from rdb$database; + commit; """ -act = isql_act('db', test_script) +substitutions = [('(-)?ALTER VIEW \\S+ failed', 'ALTER VIEW failed')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ID INTEGER Expression -View Source: -==== ====== - select 1 from rdb$database -""" - -expected_stderr = """Statement failed, SQLSTATE = 07002 -unsuccessful metadata update --ALTER VIEW TEST_VIEW failed --SQL error code = -607 --Invalid command --number of columns does not match select list +expected_stdout = """ + Statement failed, SQLSTATE = 07002 + unsuccessful metadata update + ALTER VIEW failed + -SQL error code = -607 + -Invalid command + -number of columns does not match select list """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From eb90953b3480a8c8525c4d4e88d89687b94688f6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 15:25:29 +0300 Subject: [PATCH 0751/1064] Added/Updated tests\bugs\core_3222_test.py: Re-implemented: use f-notation in order to remove hard-coded DDL string from test_script and expected_out.. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3222_test.py | 60 ++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/tests/bugs/core_3222_test.py b/tests/bugs/core_3222_test.py index 9ff626a2..00477c2c 100644 --- a/tests/bugs/core_3222_test.py +++ b/tests/bugs/core_3222_test.py @@ -7,47 +7,53 @@ DESCRIPTION: JIRA: CORE-3222 FBTEST: bugs.core_3222 +NOTES: + [27.06.2025] pzotov + Re-implemented: use f-notation in order to remove hard-coded DDL string from test_script and expected_out. + Removed 'SHOW VIEW'command because its output can change in any intensive developing FB version. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE Foo ( - Bar INTEGER, - Str CHAR(31) -); -COMMIT; +db = db_factory() + +VIEW_DDL = """ + select bar + from test + where(trim(str) = 'test') + with check option """ -db = db_factory(init=init_script) - -test_script = """CREATE VIEW VIEW_Foo ( - Bar -) AS SELECT - Bar - FROM Foo - WHERE(Trim(Str) = 'test') -WITH CHECK OPTION -; -COMMIT; -SHOW VIEW VIEW_Foo; +test_script = f""" + set list on; + set blob all; + set count on; + create table test ( + bar integer, + str char(31) + ); + commit; + + create view v_test (bar) as + {VIEW_DDL} + ; + commit; + select r.rdb$view_source as blob_id from rdb$relations r where r.rdb$relation_name = upper('v_test'); """ -act = isql_act('db', test_script) +substitutions = [('BLOB_ID .*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """BAR INTEGER Nullable -View Source: -==== ====== - SELECT - Bar - FROM Foo - WHERE(Trim(Str) = 'test') -WITH CHECK OPTION +expected_stdout = f""" + {VIEW_DDL} + Records affected: 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 24780417c94491bf502ebd16cc778bada53eff5a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 15:32:31 +0300 Subject: [PATCH 0752/1064] Added/Updated tests\bugs\core_3239_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3239_test.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_3239_test.py b/tests/bugs/core_3239_test.py index 273a1645..c6f253f9 100644 --- a/tests/bugs/core_3239_test.py +++ b/tests/bugs/core_3239_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-3239 FBTEST: bugs.core_3239 +NOTES: + [27.06.2025] pzotov + Suppressed name of altered view in order to have same expected* text for versions prior/since 6.x + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -63,27 +68,39 @@ where a.bfield = true; """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) + -expected_stdout = """ +expected_out_5x = """ PLAN (TEST INDEX (TEST_BOOL_CIAI_CI)) RULE_ID 2 RULE_ID 3 - PLAN (TEST INDEX (TEST_INT_CI_CIAI)) RULE_ID 1 - PLAN (TEST INDEX (TEST_BOOL_CIAI_CI)) RULE_ID 2 - PLAN JOIN (A INDEX (TEST_BOOL_CIAI_CI), B INDEX (TEST_INT_CI_CIAI)) RULE_ID 1 RULE_ID 4 """ -@pytest.mark.version('>=3.0') +expected_out_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_BOOL_CIAI_CI")) + RULE_ID 2 + RULE_ID 3 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_INT_CI_CIAI")) + RULE_ID 1 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_BOOL_CIAI_CI")) + RULE_ID 2 + PLAN JOIN ("A" INDEX ("PUBLIC"."TEST_BOOL_CIAI_CI"), "B" INDEX ("PUBLIC"."TEST_INT_CI_CIAI")) + RULE_ID 1 + RULE_ID 4 +""" + +@pytest.mark.intl +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 6fd7a2f7c66fd9db64ddaa1cc6b918928fb47be8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 15:34:58 +0300 Subject: [PATCH 0753/1064] Added/Updated tests\bugs\core_3283_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3283_test.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3283_test.py b/tests/bugs/core_3283_test.py index 6253b908..c5b039ea 100644 --- a/tests/bugs/core_3283_test.py +++ b/tests/bugs/core_3283_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3283 FBTEST: bugs.core_3283 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -43,14 +49,18 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_out_5x = """ PLAN SORT (JOIN (T2 INDEX (TTT_ID), T3 INDEX (TTT_ID))) PLAN (T1 INDEX (TTT_ID)) """ +expected_out_6x = """ + PLAN SORT (JOIN ("T2" INDEX ("PUBLIC"."TTT_ID"), "T3" INDEX ("PUBLIC"."TTT_ID"))) + PLAN ("T1" INDEX ("PUBLIC"."TTT_ID")) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From fefe7d1d3872efc968df6fb8e56aee9808cb7164 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 17:40:15 +0300 Subject: [PATCH 0754/1064] Added/Updated tests\bugs\core_3305_test.py: Reimplemented: make single test function for the whole code, use different variables to store output on 3.x / 4.x+5.x / 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3305_test.py | 67 ++++++++++++++---------------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/tests/bugs/core_3305_test.py b/tests/bugs/core_3305_test.py index 3b485147..27f8cf5b 100644 --- a/tests/bugs/core_3305_test.py +++ b/tests/bugs/core_3305_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3305 FBTEST: bugs.core_3305 +NOTES: + [27.06.2025] pzotov + Reimplemented: make single test function for the whole code, use different variables to store output on 3.x / 4.x+5.x / 6.x + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,67 +20,44 @@ db = db_factory() -# version: 3.0 - -test_script_1 = """ - recreate table t(v int); - commit; +test_script = """ + recreate table test(v int); set term ^; - create or alter trigger t_ai for t active after insert position 0 as + create or alter trigger test_ai for test active AFTER insert position 0 as begin new.v = 1; end ^ set term ;^ - commit; - insert into t(v) values(123); + insert into test(v) values(123); rollback; """ -act_1 = isql_act('db', test_script_1) +act = isql_act('db', test_script) -expected_stderr_1 = """ +expected_out_3x = """ Statement failed, SQLSTATE = 42000 attempted update of read-only column Statement failed, SQLSTATE = 42000 attempted update of read-only column """ -@pytest.mark.version('>=3,<4.0') -def test_1(act_1: Action): - act_1.expected_stderr = expected_stderr_1 - act_1.execute() - assert act_1.clean_stderr == act_1.clean_expected_stderr - -# version: 4.0 - -test_script_2 = """ - recreate table t(v int); - commit; - set term ^; - create or alter trigger t_ai for t active after insert position 0 as - begin - new.v = 1; - end - ^ - set term ;^ - commit; - insert into t(v) values(123); - rollback; +expected_out_5x = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.V + Statement failed, SQLSTATE = 42000 + attempted update of read-only column TEST.V """ -act_2 = isql_act('db', test_script_2) - -expected_stderr_2 = """ +expected_out_6x = """ Statement failed, SQLSTATE = 42000 - attempted update of read-only column T.V + attempted update of read-only column "PUBLIC"."TEST"."V" Statement failed, SQLSTATE = 42000 - attempted update of read-only column T.V + attempted update of read-only column "PUBLIC"."TEST"."V" """ -@pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert act_2.clean_stderr == act_2.clean_expected_stderr - +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_out_3x if act.is_version('<4') else expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 83f0851517ccddc808bbfcf2f370608ad6c4980b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 17:54:48 +0300 Subject: [PATCH 0755/1064] Added/Updated tests\bugs\core_3311_test.py: Reimplemented: it is enough to check only STDERR in this test rather that compare issued execution plans. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3311_test.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_3311_test.py b/tests/bugs/core_3311_test.py index 04d11e7d..f3569089 100644 --- a/tests/bugs/core_3311_test.py +++ b/tests/bugs/core_3311_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-3311 FBTEST: bugs.core_3311 +NOTES: + [27.06.2025] pzotov + Reimplemented: it is enough to check only STDERR in this test rather that compare issued execution plans. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -48,20 +53,12 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN (TEST NATURAL) - PLAN (TEST ORDER TEST_ID) - PLAN (TEST NATURAL) - PLAN (TEST ORDER TEST_ID) - PLAN (TEST NATURAL) - PLAN (TEST ORDER TEST_ID) - PLAN JOIN (S TEST INDEX (TEST_ID), T INDEX (TEST_ID)) - PLAN JOIN (S TEST ORDER TEST_ID, T INDEX (TEST_ID)) +expected_stderr = """ """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout + act.expected_stderr = expected_stderr + act.execute() # ::: do not use 'combine_outpt = True! We have to check here only STDERR ::: + assert act.clean_stderr == act.clean_expected_stderr From 227bb7e4f5d8198a8c024f8609012946110868a2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:03:26 +0300 Subject: [PATCH 0756/1064] Added/Updated tests\bugs\core_3312_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3312_test.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_3312_test.py b/tests/bugs/core_3312_test.py index 9d32ae36..4c0815e1 100644 --- a/tests/bugs/core_3312_test.py +++ b/tests/bugs/core_3312_test.py @@ -3,10 +3,17 @@ """ ID: issue-3679 ISSUE: 3679 -TITLE: Sub-optimal join plan when the slave table depends on the master one via the OR predicate +TITLE: Sub-optimal join plan when the slave table depends on the master via the "OR" predicate DESCRIPTION: JIRA: CORE-3312 FBTEST: bugs.core_3312 +NOTES: + [27.06.2025] pzotov + Added substitutions in order to suppress digital suffix of indices name (in 'RDB$INDEX_'). + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,7 +21,8 @@ db = db_factory() -test_script = """SET PLANONLY ON; +test_script = """ +SET PLANONLY ON; select * from rdb$relations r join rdb$security_classes sc @@ -27,16 +35,24 @@ or (r.rdb$default_class = sc.rdb$security_class and r.rdb$relation_id = 1); """ -act = isql_act('db', test_script) -expected_stdout = """ -PLAN JOIN (R NATURAL, SC INDEX (RDB$INDEX_7, RDB$INDEX_7)) -PLAN JOIN (R INDEX (RDB$INDEX_1, RDB$INDEX_1), SC INDEX (RDB$INDEX_7, RDB$INDEX_7)) +substitutions = [ ('[ \t]+', ' '), ('RDB\\$INDEX_\\d+', 'RDB$INDEX_*') ] +act = isql_act('db', test_script, substitutions = substitutions) + + +expected_out_5x = """ + PLAN JOIN (R NATURAL, SC INDEX (RDB$INDEX_*, RDB$INDEX_*)) + PLAN JOIN (R INDEX (RDB$INDEX_*, RDB$INDEX_*), SC INDEX (RDB$INDEX_*, RDB$INDEX_*)) """ +expected_out_6x = """ + PLAN JOIN ("R" NATURAL, "SC" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*")) + PLAN JOIN ("R" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*"), "SC" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*")) +""" + +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 51e5856450eec7f12e8800e71474b4e312327265 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:18:33 +0300 Subject: [PATCH 0757/1064] Added/Updated tests\bugs\core_3338_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3338_test.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_3338_test.py b/tests/bugs/core_3338_test.py index 4242ad09..f47b0ae2 100644 --- a/tests/bugs/core_3338_test.py +++ b/tests/bugs/core_3338_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3338 FBTEST: bugs.core_3338 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,14 +35,18 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_out_5x = """ PLAN (T INDEX (T_N2_COALESCE)) PLAN (T INDEX (T_N2_DECODE)) """ -@pytest.mark.version('>=3.0') +expected_out_6x = """ + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_N2_COALESCE")) + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."T_N2_DECODE")) +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 7c250d5eb0cd99da0565984edf0a07868a2b0ee8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:29:57 +0300 Subject: [PATCH 0758/1064] Added/Updated tests\bugs\core_3353_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3353_test.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3353_test.py b/tests/bugs/core_3353_test.py index 77380bfa..c784f1d1 100644 --- a/tests/bugs/core_3353_test.py +++ b/tests/bugs/core_3353_test.py @@ -17,6 +17,12 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,14 +57,19 @@ def test_1(act: Action): # version: 4.0 -expected_stdout_2 = """ +expected_out_5x = """ 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8 """ +expected_out_6x = """ + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 SYSTEM.UTF8 + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 SYSTEM.UTF8 +""" + @pytest.mark.version('>=4.0') def test_2(act: Action): - act.expected_stdout = expected_stdout_2 + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1149c8b54a948ce7bc6c3d195bee0e76794d6568 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:35:36 +0300 Subject: [PATCH 0759/1064] Added/Updated tests\bugs\core_3357_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3357_test.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_3357_test.py b/tests/bugs/core_3357_test.py index d592aac6..25c144b3 100644 --- a/tests/bugs/core_3357_test.py +++ b/tests/bugs/core_3357_test.py @@ -5,13 +5,20 @@ ISSUE: 3723 TITLE: Generators are set to 0 after restore DESCRIPTION: - FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): - statement 'alter sequence restart with 0' changes rdb$generators.rdb$initial_value to -1 thus - next call of gen_id(,1) will return 0 (ZERO!) rather than 1. - See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d - This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt + FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): + statement 'alter sequence restart with 0' changes rdb$generators.rdb$initial_value to -1 thus + next call of gen_id(,1) will return 0 (ZERO!) rather than 1. + See also CORE-6084 and related commit: + https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d + This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt JIRA: CORE-3357 FBTEST: bugs.core_3357 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,20 +36,21 @@ act = python_act('db') -# version: 3.0 - -expected_stdout_3 = """ +expected_out_3x = """ Generator G1, current value: 9223372036854775807, initial value: 9223372036854775807, increment: -2147483647 Generator G2, current value: -9223372036854775808, initial value: -9223372036854775808, increment: 2147483647 """ -# version: 4.0 - -expected_stdout_4 = """ +expected_out_5x = """ Generator G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647 Generator G2, current value: 9223372034707292161, initial value: -9223372036854775808, increment: 2147483647 """ +expected_out_6x = """ + Generator PUBLIC.G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647 + Generator PUBLIC.G2, current value: 9223372034707292161, initial value: -9223372036854775808, increment: 2147483647 +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): with act.connect_server() as srv: @@ -51,6 +59,7 @@ def test_1(act: Action): backup.seek(0) srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags=SrvRestoreFlag.REPLACE) - act.expected_stdout = expected_stdout_4 if act.is_version('>=4') else expected_stdout_3 - act.isql(switches=[], input="show sequ g1; show sequ g2;") + + act.expected_stdout = expected_out_3x if act.is_version('<4') else expected_out_5x if act.is_version('<6') else expected_out_6x + act.isql(switches = ['-q'], input="show sequ g1; show sequ g2;", combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From d3fec85074f799582003c85b7ce7117da3c05f5f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:43:46 +0300 Subject: [PATCH 0760/1064] Added/Updated tests\bugs\core_3364_test.py: Adjusted substitutions in order to suppress output of BLOB_ID --- tests/bugs/core_3364_test.py | 52 +++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_3364_test.py b/tests/bugs/core_3364_test.py index aed19b66..de8b74ff 100644 --- a/tests/bugs/core_3364_test.py +++ b/tests/bugs/core_3364_test.py @@ -35,33 +35,49 @@ test_script = """ set list on; set blob all; - select rdb$debug_info from rdb$procedures where upper(rdb$procedure_name) = upper('sp_test'); + select rdb$debug_info as blob_id from rdb$procedures where upper(rdb$procedure_name) = upper('sp_test'); """ -act = isql_act('db', test_script, substitutions=[('RDB\\$DEBUG_INFO', ''), ('-', ''), - ('[0-9]+[ ]+[0-9]+[ ]+[0-9]+', '')]) +''' +BLOB_ID 1a:f0 +Parameters: +Number Name Type +-------------------------------------------------- +0 A_N INPUT +0 N_FACT OUTPUT +Variables: +Number Name +------------------------------------------- +0 N_FACT +BLR to Source mapping: +BLR offset Line Column +-------------------------------- +36 2 5 +38 3 9 +73 5 9 +92 6 9 +94 7 11 +116 8 11 +142 10 9 +''' + +substitutions=[ ('BLOB_ID .*', ''), + ('[ \t]+', ' '), + ('-', ''), + ('\\d+[ ]+\\d+[ ]+\\d+', '') + ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - RDB$DEBUG_INFO 1a:f0 Parameters: - Number Name Type - -------------------------------------------------- - 0 A_N INPUT - 0 N_FACT OUTPUT + Number Name Type + 0 A_N INPUT + 0 N_FACT OUTPUT Variables: Number Name - ------------------------------------------- 0 N_FACT BLR to Source mapping: - BLR offset Line Column - -------------------------------- - 36 2 5 - 38 3 9 - 73 5 9 - 92 6 9 - 94 7 11 - 116 8 11 - 142 10 9 + BLR offset Line Column """ @pytest.mark.version('>=3.0') From de4f4fa50fdd2568b7d0dce62c2322bc1ab3ee10 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 18:46:48 +0300 Subject: [PATCH 0761/1064] Added/Updated tests\bugs\core_3394_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3394_test.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_3394_test.py b/tests/bugs/core_3394_test.py index 7c452ef9..ca6d91a8 100644 --- a/tests/bugs/core_3394_test.py +++ b/tests/bugs/core_3394_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3394 FBTEST: bugs.core_3394 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -30,18 +36,25 @@ rollback; """ -act = isql_act('db', test_script, substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) +act = isql_act('db', test_script, substitutions=[('(-)?At block line: [\\d]+, col: [\\d]+', 'At block line')]) -expected_stderr = """ +expected_out_5x = """ Statement failed, SQLSTATE = 23000 violation of PRIMARY or UNIQUE KEY constraint "T_PK" on table "T" -Problematic key value is ("ID" = 1) - -At block line: 5, col: 7 + At block line +""" + +expected_out_6x = """ + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "T_PK" on table "PUBLIC"."T" + -Problematic key value is ("ID" = 1) + At block line """ -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +@pytest.mark.version('>=3.0') +def test_2(act: Action): + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 8a03e76081961bd1afd0513e0f88600c9cd0a447 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 19:38:36 +0300 Subject: [PATCH 0762/1064] Added/Updated tests\bugs\core_3419_test.py: Reimplemented: it is enought to check that first lines of error message appear, w/o name of trigger. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3419_test.py | 47 +++++++++++------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/tests/bugs/core_3419_test.py b/tests/bugs/core_3419_test.py index c25a7bb7..18c6a798 100644 --- a/tests/bugs/core_3419_test.py +++ b/tests/bugs/core_3419_test.py @@ -7,13 +7,18 @@ DESCRIPTION: JIRA: CORE-3419 FBTEST: bugs.core_3419 +NOTES: + [27.06.2025] pzotov + Reimplemented: it is enought to check that first lines of error message appear, w/o name of trigger. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ +import locale import pytest from firebird.qa import * db = db_factory() - test_script = """ set autoddl off; commit; @@ -21,7 +26,7 @@ commit; set term ^; -- This trigger will fire 1001 times before exception raising: - create or alter trigger trg_trans_start + create or alter trigger tx_trg active on transaction start position 0 as begin @@ -34,39 +39,15 @@ set transaction; """ -act = isql_act('db', test_script, substitutions=[('line: [0-9]+, col: [0-9]+', 'line: , col: ')]) +act = isql_act('db', substitutions=[('(-)?At trigger .*', '')]) -expected_stderr = """ +expected_out = f""" Statement failed, SQLSTATE = 54001 Too many concurrent executions of the same request - -At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' line: 5, col: 9 - At trigger 'TRG_TRANS_START' ... """ -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute(charset='utf8') - assert act.clean_stderr == act.clean_expected_stderr - +@pytest.mark.version('>=3.0') +def test_2(act: Action): + act.expected_stdout = expected_out + act.isql(switches=['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 380836294fda5907096a8a1154cd7a41995175bf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 19:44:20 +0300 Subject: [PATCH 0763/1064] Added/Updated tests\bugs\core_3421_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3421_test.py | 52 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_3421_test.py b/tests/bugs/core_3421_test.py index 5de88dee..3e3338c2 100644 --- a/tests/bugs/core_3421_test.py +++ b/tests/bugs/core_3421_test.py @@ -12,41 +12,41 @@ Added 'Error reading/writing' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see message related to any error. + + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - create or alter procedure sp_test as begin end; - commit; +db = db_factory() + +test_script = """ + set bail on; + set list on; + set sqlda_display on; + recreate table test( id bigint constraint test_id_pk primary key using index test_id_pk, s01 varchar(512) ); - commit; - set term ^; create or alter procedure sp_test( a_id type of column test.id, a_s01 type of column test.s01) - returns(o_id type of column test.id, o_s01 type of column test.s01) - as + returns(o_id type of column test.id, o_s01 type of column test.s01) as begin - execute statement ('update or insert into test(id, s01) values( :x, :y ) returning id, s01') - ( x := a_id, y := a_s01 ) - into o_id, o_s01; - suspend; + execute statement ('update or insert into test(id, s01) values( :x, :y ) returning id, s01') + ( x := a_id, y := a_s01 ) + into o_id, o_s01; + suspend; end ^ set term ;^ commit; -""" - -db = db_factory(init=init_script) -test_script = """ - set bail on; - set list on; - set sqlda_display on; set planonly; set term ^; execute block returns(o_id type of column test.id, o_s01 type of column test.s01) @@ -65,7 +65,7 @@ # act = isql_act('db', test_script, substitutions = [ ('^((?!(sqltype|(Error\\s+(reading|writing)) )).)*$', ''), ('[ \t]+', ' ') ] ) -expected_stdout = """ +expected_stdout_5x = """ 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 NONE 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 @@ -74,9 +74,17 @@ 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 NONE """ -@pytest.mark.version('>=3.0') +expected_stdout_6x = """ + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 SYSTEM.NONE + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 SYSTEM.NONE + 01: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 512 charset: 0 SYSTEM.NONE +""" + +@pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 61fef55e542adafed9df2c883fb1b657eb5ce9e9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 19:47:18 +0300 Subject: [PATCH 0764/1064] Added/Updated tests\bugs\core_3450_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3450_test.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_3450_test.py b/tests/bugs/core_3450_test.py index 4e5b8521..111a4541 100644 --- a/tests/bugs/core_3450_test.py +++ b/tests/bugs/core_3450_test.py @@ -8,16 +8,11 @@ JIRA: CORE-3450 FBTEST: bugs.core_3450 NOTES: - [30.11.2016] pzotov - It seems that we have regression in current 4.0 snapshots (elapsed time more than 10x comparing with 2.5). - Also, 4.0 has different plan comparing with 3.0. - After discuss with dimitr it was decided to commit this test into fbt-repo in order to have constant - reminder about this issue. - Currently this test should FAIL on 4.0. - - [22.09.2022] pzotov - Removed SKIP notation because test works fine on FB 4.0.1 - Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.736 + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -101,13 +96,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (JOIN (P1 NATURAL, T1 INDEX (TEST_1_F2)), T2 INDEX (TEST_2_F1), T3 INDEX (TEST_3_F1)) """ +expected_stdout_6x = """ + PLAN JOIN (JOIN ("P1" NATURAL, "T1" INDEX ("PUBLIC"."TEST_1_F2")), "T2" INDEX ("PUBLIC"."TEST_2_F1"), "T3" INDEX ("PUBLIC"."TEST_3_F1")) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 5257764573088e00b60b3b7a4790b225bec4a473 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 19:50:45 +0300 Subject: [PATCH 0765/1064] Added/Updated tests\bugs\core_3474_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3474_test.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_3474_test.py b/tests/bugs/core_3474_test.py index 497f618f..bf2d522c 100644 --- a/tests/bugs/core_3474_test.py +++ b/tests/bugs/core_3474_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3474 FBTEST: bugs.core_3474 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -36,27 +42,32 @@ rows 1; """ -act = isql_act('db', test_script, substitutions=[('-At line.*', '')]) +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' '), ('(-)?At line.*', '')]) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -E.EMP_NO EMP_2 2 NAME_2 Nelson PROJ_2 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42S22 Dynamic SQL Error -SQL error code = -206 -Column unknown - -E.EMP_NO + -"E"."EMP_NO" + EMP_2 2 + NAME_2 Nelson + PROJ_2 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e9b662b653307ab8b2692fd8420eeffe725e2220 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:07:39 +0300 Subject: [PATCH 0766/1064] Added/Updated tests\bugs\core_3491_test.py: Removed 'SHOW' command. It is enough to check twise results of query to rdb$ tables - they must be same. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3491_test.py | 77 +++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/tests/bugs/core_3491_test.py b/tests/bugs/core_3491_test.py index 77d39214..a30c2384 100644 --- a/tests/bugs/core_3491_test.py +++ b/tests/bugs/core_3491_test.py @@ -7,43 +7,64 @@ DESCRIPTION: JIRA: CORE-3491 FBTEST: bugs.core_3491 +NOTES: + [27.06.2025] pzotov + Removed 'SHOW' command. It is enough to check twise results of query to rdb$ tables - they must be same. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table aaa (a integer); -commit; -set term !!; -create or alter procedure bbb -returns (b type of column aaa.a) -as -begin - suspend; -end!! -set term ;!! -commit; -""" +db = db_factory() + +test_script = """ + set list on; + + create view v_info as + select rf.rdb$field_name fld_name, f.rdb$field_type fld_type, f.rdb$field_length fld_length, f.rdb$field_scale fld_scale + from rdb$relation_fields rf + left join rdb$fields f on rf.rdb$field_source = f.rdb$field_name + where rf.rdb$relation_name = upper('test'); -db = db_factory(init=init_script) - -test_script = """show table aaa; -set term !!; -create or alter procedure bbb -returns (b varchar(10)) -as -begin - suspend; -end!! -set term ;!! -commit; -show table aaa; + create table test (f01 integer); + commit; + set term ^; + create or alter procedure sp_test returns (o_result type of column test.f01) as + begin + suspend; + end^ + set term ;^ + commit; + + select 'point-1' as msg, v.* from v_info v; + + set term ^; + create or alter procedure sp_test returns (o_result varchar(10)) as + begin + suspend; + end^ + set term ;^ + commit; + + select 'point-2' as msg, v.* from v_info v; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions=[('[ \t]+', ' '), ('Table: .*', '')]) + +expected_stdout = """ + MSG point-1 + FLD_NAME F01 + FLD_TYPE 8 + FLD_LENGTH 4 + FLD_SCALE 0 -expected_stdout = """A INTEGER Nullable -A INTEGER Nullable + MSG point-2 + FLD_NAME F01 + FLD_TYPE 8 + FLD_LENGTH 4 + FLD_SCALE 0 """ @pytest.mark.version('>=3') From 8ed2e772616a7800831cb3cb2e37ec8782d46a9c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:10:30 +0300 Subject: [PATCH 0767/1064] Added/Updated tests\bugs\core_3491_test.py: minor change: added comment. --- tests/bugs/core_3491_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_3491_test.py b/tests/bugs/core_3491_test.py index a30c2384..c117a7d4 100644 --- a/tests/bugs/core_3491_test.py +++ b/tests/bugs/core_3491_test.py @@ -10,6 +10,7 @@ NOTES: [27.06.2025] pzotov Removed 'SHOW' command. It is enough to check twise results of query to rdb$ tables - they must be same. + Test script was checked on 2.5.0.26074 - bug has been confirmed. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ From 4b439a08da106658ca412a81ade4858af7ec0b5e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:24:51 +0300 Subject: [PATCH 0768/1064] Added/Updated tests\bugs\core_3502_test.py: Added subst to suppress output: it is enough to display error message w/o concrete coulmn name for this test. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3502_test.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_3502_test.py b/tests/bugs/core_3502_test.py index 8f315753..1ea64193 100644 --- a/tests/bugs/core_3502_test.py +++ b/tests/bugs/core_3502_test.py @@ -7,17 +7,19 @@ DESCRIPTION: JIRA: CORE-3502 FBTEST: bugs.core_3502 +NOTES: + [27.06.2025] pzotov + Added subst to suppress output: it is enough to display error message w/o concrete coulmn name for this test. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - set autoddl on; - commit; - create or alter procedure p as begin end; - commit; +db = db_factory() +test_script = """ create or alter view v (id) as select rdb$relation_id from rdb$database; commit; @@ -29,29 +31,25 @@ end^ set term ;^ commit; -""" -db = db_factory(init=init_script) - -test_script = """ execute procedure p; commit; + drop view v; """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [('(-)?COLUMN .*', 'COLUMN *')]) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -COLUMN V.ID + COLUMN * -there are 1 dependencies """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1f5b777798c9daf737b9ab9d2db0578777172ab3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:26:29 +0300 Subject: [PATCH 0769/1064] Updated tests\bugs\core_3509_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_3509_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3509_test.py b/tests/bugs/core_3509_test.py index c3b05241..a6b7d02f 100644 --- a/tests/bugs/core_3509_test.py +++ b/tests/bugs/core_3509_test.py @@ -51,10 +51,10 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 - CREATE OR ALTER PROCEDURE DUPLICATE_OUTPUT_ARGS failed + CREATE OR ALTER PROCEDURE "PUBLIC"."DUPLICATE_OUTPUT_ARGS" failed -Dynamic SQL Error -SQL error code = -637 - -duplicate specification of A_DUP - not supported + -duplicate specification of "A_DUP" - not supported """ @pytest.mark.version('>=3.0') From 9699c018115973f06f1a34eae81e4f3efdaf63e8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:28:33 +0300 Subject: [PATCH 0770/1064] Added/Updated tests\bugs\core_3530_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3530_test.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3530_test.py b/tests/bugs/core_3530_test.py index a56e3795..3cf70cb6 100644 --- a/tests/bugs/core_3530_test.py +++ b/tests/bugs/core_3530_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3530 FBTEST: bugs.core_3530 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -55,7 +61,7 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST NATURAL) PLAN (TEST NATURAL) PLAN (TEST NATURAL) @@ -63,9 +69,16 @@ Records affected: 0 """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST2" NATURAL) + Records affected: 0 +""" + @pytest.mark.version('>=3.0.2') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From ce037d3884ba0c39139f2e5deb212052cad3e640 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:39:49 +0300 Subject: [PATCH 0771/1064] Added/Updated tests\bugs\core_3545_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3545_test.py | 71 +++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_3545_test.py b/tests/bugs/core_3545_test.py index 8fa80156..ecf31a6d 100644 --- a/tests/bugs/core_3545_test.py +++ b/tests/bugs/core_3545_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3545 FBTEST: bugs.core_3545 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -117,49 +123,62 @@ act = isql_act('db', test_script, substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) -expected_stdout = """ - ID 1 - N 4 - - ID 3 - N 4 -""" - -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 validation error for column "TEST"."N", value "399" - Statement failed, SQLSTATE = 23000 validation error for column "TEST"."N", value "50" - Statement failed, SQLSTATE = 23000 validation error for column "TEST"."N", value "399" - Statement failed, SQLSTATE = 23000 validation error for column "TEST"."N", value "50" - + ID 1 + N 4 + ID 3 + N 4 Statement failed, SQLSTATE = 42000 validation error for variable VAR2_ASSIGNMENT_WITHOUT_CAST, value "50" - -At block line: 4, col: 7 - + -At block line Statement failed, SQLSTATE = 42000 validation error for variable VAR2_ASSIGNMENT_WITHOUT_CAST, value "399" - -At block line: 4, col: 7 - + -At block line Statement failed, SQLSTATE = 42000 validation error for variable VAR2_CAST_INT_TO_DOMAIN, value "50" - -At block line: 4, col: 7 - + -At block line Statement failed, SQLSTATE = 42000 validation error for variable VAR2_CAST_INT_TO_DOMAIN, value "399" - -At block line: 4, col: 7 + -At block line +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."N", value "399" + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."N", value "50" + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."N", value "399" + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."N", value "50" + ID 1 + N 4 + ID 3 + N 4 + Statement failed, SQLSTATE = 42000 + validation error for variable "VAR2_ASSIGNMENT_WITHOUT_CAST", value "50" + -At block line + Statement failed, SQLSTATE = 42000 + validation error for variable "VAR2_ASSIGNMENT_WITHOUT_CAST", value "399" + -At block line + Statement failed, SQLSTATE = 42000 + validation error for variable "VAR2_CAST_INT_TO_DOMAIN", value "50" + -At block line + Statement failed, SQLSTATE = 42000 + validation error for variable "VAR2_CAST_INT_TO_DOMAIN", value "399" + -At block line """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0220deb75d355b447323370aee710b4a1212dd4c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:43:58 +0300 Subject: [PATCH 0772/1064] Added/Updated tests\bugs\core_3547_test.py: Output of constraint name is suppressed (not needed for this test). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3547_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3547_test.py b/tests/bugs/core_3547_test.py index abd5a2d1..cbfea4e1 100644 --- a/tests/bugs/core_3547_test.py +++ b/tests/bugs/core_3547_test.py @@ -15,8 +15,13 @@ Added substitution in order to stop comparison after 15th digit ("COL = 0.000000000000000"). We have to ensure that one can not insert duplicate (-0e0). It is enough to show concrete value of problematic key with accuracy 15 digits. - Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.730 - both Linux and Windows + + [27.06.2025] pzotov + Output of constraint name is suppressed (not needed for this test). + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + """ import pytest @@ -56,7 +61,8 @@ -- ^ """ -act = isql_act('db', test_script, substitutions = [(' = 0.0000000000000000', ' = 0.000000000000000')]) +substitutions = [ (' = 0.0000000000000000', ' = 0.000000000000000'), ('constraint .*', 'constraint') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ where id = 0 1 From 6fffecc19284051fc90db3415c0161c24e8752e1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:50:21 +0300 Subject: [PATCH 0773/1064] Added/Updated tests\bugs\core_3549_test.py: added comments --- tests/bugs/core_3549_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/bugs/core_3549_test.py b/tests/bugs/core_3549_test.py index 3cfd8e92..e53163db 100644 --- a/tests/bugs/core_3549_test.py +++ b/tests/bugs/core_3549_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-3549 FBTEST: bugs.core_3549 +NOTES: + [27.06.2025] pzotov + *** DEFERRED *** + Test failed since 6.0.0.834. PROBABLY NEEDS TO BE REFACTORED / REIMPLEMENTED. + https://github.com/FirebirdSQL/firebird/issues/3905#issuecomment-826222236 """ import pytest From 9d1bfa78a1b84e1dca1c9540e1d282322f040bea Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:53:36 +0300 Subject: [PATCH 0774/1064] Added/Updated tests\bugs\core_3553_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3553_test.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_3553_test.py b/tests/bugs/core_3553_test.py index 5f9fe25b..98baf05d 100644 --- a/tests/bugs/core_3553_test.py +++ b/tests/bugs/core_3553_test.py @@ -13,6 +13,12 @@ FB 5.0.0.455 and later: data sources with equal cardinality now present in the HASH plan in order they are specified in the query. Reversed order was used before this build. Because of this, two cases of expected stdout must be taken in account, see variables 'fb3x_checked_stdout' and 'fb5x_checked_stdout'. + + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,17 +35,21 @@ act = isql_act('db', test_script) -fb3x_checked_stdout = """ +expected_stdout_4x = """ PLAN HASH (D2 NATURAL, D1 NATURAL) """ -fb5x_checked_stdout = """ +expected_stdout_5x = """ PLAN HASH (D1 NATURAL, D2 NATURAL) """ +expected_stdout_6x = """ + PLAN HASH ("D1" NATURAL, "D2" NATURAL) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute() assert act.clean_stdout == act.clean_expected_stdout From 8b02085e7a3970fda9838b90293c0962b8c55ff6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:56:13 +0300 Subject: [PATCH 0775/1064] Added/Updated tests\bugs\core_3569_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3569_test.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_3569_test.py b/tests/bugs/core_3569_test.py index 3b35d648..1e25496d 100644 --- a/tests/bugs/core_3569_test.py +++ b/tests/bugs/core_3569_test.py @@ -12,6 +12,12 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -42,14 +48,20 @@ # act = isql_act('db', test_script, substitutions = [ ('^((?!(SQLSTATE|exceeds|maximum|limit|sqltype|literal)).)*$', ''), ('[ \t]+', ' ') ] ) -expected_stdout = """ +expected_stdout_5x = """ 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32765 charset: 0 NONE 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32766 charset: 0 NONE 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32767 charset: 0 NONE """ +expected_stdout_6x = """ + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32765 charset: 0 SYSTEM.NONE + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32766 charset: 0 SYSTEM.NONE + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 32767 charset: 0 SYSTEM.NONE +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From dad7064c83d2ef67736bf319e40f834c84778388 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 20:59:26 +0300 Subject: [PATCH 0776/1064] Added/Updated tests\bugs\core_3594_test.py: Suppressed output of procedure name (no needed for this test). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3594_test.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_3594_test.py b/tests/bugs/core_3594_test.py index 662df2ba..de088ec8 100644 --- a/tests/bugs/core_3594_test.py +++ b/tests/bugs/core_3594_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-3594 FBTEST: bugs.core_3594 +NOTES: + [27.06.2025] pzotov + Suppressed output of procedure name (no needed for this test). + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -50,25 +55,26 @@ -- -string right truncation """ -act = isql_act('db', test_script, substitutions=[('line: .*', 'line'), ('col: .*', 'col')]) +substitutions=[('line: .*', 'line'), ('col: .*', 'col'), ('(-)?At procedure .*', 'At procedure')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = 22001 arithmetic exception, numeric overflow, or string truncation -string right truncation -expected length 50, actual 60 - -At procedure 'SP_OVERFLOWED_1' line: 3, col: 5 + At procedure Statement failed, SQLSTATE = 22001 arithmetic exception, numeric overflow, or string truncation -string right truncation -expected length 59, actual 60 - -At procedure 'SP_OVERFLOWED_2' line: 3, col: 5 + At procedure """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a7c645be7a5986886de3901e3e952b86135aecc3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 21:14:22 +0300 Subject: [PATCH 0777/1064] Added/Updated tests\bugs\core_3598_test.py: See notes. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3598_test.py | 61 +++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/tests/bugs/core_3598_test.py b/tests/bugs/core_3598_test.py index a1a32f89..e82a0a60 100644 --- a/tests/bugs/core_3598_test.py +++ b/tests/bugs/core_3598_test.py @@ -17,32 +17,36 @@ Finally (after ISQL will finish), we stop trace and parse its log. For *each* table TWO lines with performance statristics must exist: both for COMMIT and ROLLBACK events. -[08.02.2022] pcisar - Fails on Windows 3.0.8 with unexpected additional output line: - + Statement statistics detected for ROLLBACK - Statement statistics detected for COMMIT - Statement statistics detected for COMMIT - Statement statistics detected for ROLLBACK - Found performance block header - Found table statistics for TFIX - Statement statistics detected for COMMIT - Statement statistics detected for ROLLBACK - Found performance block header - Found table statistics for GTT_SSN - Statement statistics detected for COMMIT - Statement statistics detected for ROLLBACK - -[04.03.2022] pzotov: RESOLVED. - Problem on Windows was caused by excessive query: - "select current_user, current_role from rdb$database" - -- which is done by ISQL 3.x when it gets commands from STDIN via PIPE mechanism. - Discussed with Alex et al, since 28-feb-2022 18:05 +0300. - Alex explanation: 28-feb-2022 19:52 +0300 - subj: "Firebird new-QA: weird result for trivial test (outcome depends on presence of... running trace session!)" - - JIRA: CORE-3598 FBTEST: bugs.core_3598 +NOTES: + [08.02.2022] pcisar + Fails on Windows 3.0.8 with unexpected additional output line: + + Statement statistics detected for ROLLBACK + Statement statistics detected for COMMIT + Statement statistics detected for COMMIT + Statement statistics detected for ROLLBACK + Found performance block header + Found table statistics for TFIX + Statement statistics detected for COMMIT + Statement statistics detected for ROLLBACK + Found performance block header + Found table statistics for GTT_SSN + Statement statistics detected for COMMIT + Statement statistics detected for ROLLBACK + + [04.03.2022] pzotov: RESOLVED. + Problem on Windows was caused by excessive query: + "select current_user, current_role from rdb$database" + -- which is done by ISQL 3.x when it gets commands from STDIN via PIPE mechanism. + Discussed with Alex et al, since 28-feb-2022 18:05 +0300. + Alex explanation: 28-feb-2022 19:52 +0300 + subj: "Firebird new-QA: weird result for trivial test (outcome depends on presence of... running trace session!)" + + [27.06.2025] pzotov + Added substitutions to suppress output of "PUBLIC" schema name in expected output (no needed for this test). + Added check for presence `"PUBLIC".` prefix in thetable statistics for table names that are used in this test. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -57,7 +61,9 @@ db = db_factory(init=init_script) -act = python_act('db') +substitutions = [('for \"PUBLIC\".\"TFIX\"', 'for TFIX'), ('for \"PUBLIC\".\"GTT_SSN\"', 'for GTT_SSN'), ] + +act = python_act('db', substitutions = substitutions) test_script = """ set autoddl off; @@ -135,6 +141,11 @@ def test_1(act: Action, capsys): print('Found performance block header') if line.startswith('TFIX') or line.startswith('GTT_SSN') or line.startswith('GTT_TRA'): print(f'Found table statistics for {line.split()[0]}') + + # Added for FB 6.x: SCHEMA name presents since 6.0.0.834: + if line.startswith('"PUBLIC"."TFIX"') or line.startswith('"PUBLIC"."GTT_SSN"') or line.startswith('"PUBLIC"."GTT_TRA"'): + print(f'Found table statistics for {line.split()[0]}') + # Check act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out From f521a473fd0b56dcf067c983b5f70dab41dd470a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:28:14 +0300 Subject: [PATCH 0778/1064] Added/Updated tests\bugs\core_3610_test.py: Output of constraint name is suppressed (not needed for this test). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3610_test.py | 59 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/tests/bugs/core_3610_test.py b/tests/bugs/core_3610_test.py index c6fa76a1..89553613 100644 --- a/tests/bugs/core_3610_test.py +++ b/tests/bugs/core_3610_test.py @@ -7,15 +7,17 @@ DESCRIPTION: JIRA: CORE-3610 FBTEST: bugs.core_3610 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), - ('335544382 : Problematic key', '335545072 : Problematic key'), - ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] - db = db_factory() test_script = """ @@ -40,28 +42,24 @@ set term ;^ rollback; - -- |||||||||||||||||||||||||||| - -- ###################################||| FB 4.0+, SS and SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - delete from mon$attachments where mon$attachment_id != current_connection; - commit; - set list on; select * from test; """ +substitutions = [('[ \t]+', ' '), + ('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:'), + ('335544382 : Problematic key', '335545072 : Problematic key'), + ('-At block line: [\\d]+, col: [\\d]+', '-At block line')] act = isql_act('db', test_script, substitutions=substitutions) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_execute2 : + 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + 335545072 : Problematic key value is ("F01" = 1) + Statement : update test set f01 = ? where id = ? + Data source : Firebird::localhost: + -At block line ID 1 F01 1 ID 2 @@ -70,22 +68,25 @@ F01 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 Execute statement error at isc_dsql_execute2 : - 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + 335544665 : violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "PUBLIC"."TEST" 335545072 : Problematic key value is ("F01" = 1) Statement : update test set f01 = ? where id = ? Data source : Firebird::localhost: - -At block line: 3, col: 9 + -At block line + ID 1 + F01 1 + ID 2 + F01 + ID 3 + F01 """ @pytest.mark.es_eds @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4b7d0e69fe794443b0805d674adf487fa42ecb13 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:31:01 +0300 Subject: [PATCH 0779/1064] Added/Updated tests\bugs\core_3627_test.py: Output of constraint name is suppressed (not needed for this test). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3627_test.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_3627_test.py b/tests/bugs/core_3627_test.py index a4882841..c3949ae0 100644 --- a/tests/bugs/core_3627_test.py +++ b/tests/bugs/core_3627_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3627 FBTEST: bugs.core_3627 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -38,15 +44,20 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 attempt to store duplicate value (visible to active transactions) in unique index "CLASSIDKSGIDX" -Problematic key value is ("CLASSID" = 1, "KSGFK" = NULL) """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "PUBLIC"."CLASSIDKSGIDX" + -Problematic key value is ("CLASSID" = 1, "KSGFK" = NULL) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a76b5fe5ed24c87fd61a331f3819cc2a6b52f781 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:40:22 +0300 Subject: [PATCH 0780/1064] Added/Updated tests\bugs\core_3672_test.py: Added 'SCHEMA_PREFIX' to be substituted in expected_out on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3672_test.py | 51 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_3672_test.py b/tests/bugs/core_3672_test.py index 97f0c2d9..4cd76ffc 100644 --- a/tests/bugs/core_3672_test.py +++ b/tests/bugs/core_3672_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-3672 FBTEST: bugs.core_3672 +NOTES: + [27.06.2025] pzotov + Added 'SCHEMA_PREFIX' to be substituted in expected_out on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,7 +18,14 @@ db = db_factory() -test_script = """ +IDX_EXPR_1 = 'substring(col1 from 1 for 169)' +IDX_EXPR_2 = 'substring(trim( col2 from col1 ) from 1 for 169) ' +IDX_EXPR_3 = 'col2' +IDX_EXPR_4 = 'substring(col2 from 1 for 169)' +IDX_EXPR_5 = 'col3' +IDX_EXPR_6 = 'substring(col3 from 1 for 169)' + +test_script = f""" recreate table test( col1 varchar(8190) character set utf8 collate unicode_ci_ai ,col2 computed by ( substring(col1 from 1 for 169) ) @@ -27,12 +38,12 @@ -- max_key_length = floor( (page_size / 4 - 9) / N ) = 169 characters. -- Verify that we CAN do that w/o error: - create index test_col1_idx_a on test computed by ( substring(col1 from 1 for 169) ); - create index test_col1_idx_b on test computed by ( substring(trim( col2 from col1 ) from 1 for 169) ); - create index test_col2_idx_a on test computed by ( col2 ); - create index test_col2_idx_b on test computed by ( substring(col2 from 1 for 169) ); - create index test_col3_idx_a on test computed by ( col3 ); - create index test_col3_idx_b on test computed by ( substring(col3 from 1 for 169) ); + create index test_col1_idx_a on test computed by ( {IDX_EXPR_1} ); + create index test_col1_idx_b on test computed by ( {IDX_EXPR_2} ); + create index test_col2_idx_a on test computed by ( {IDX_EXPR_3} ); + create index test_col2_idx_b on test computed by ( {IDX_EXPR_4} ); + create index test_col3_idx_a on test computed by ( {IDX_EXPR_5} ); + create index test_col3_idx_b on test computed by ( {IDX_EXPR_6} ); commit; -- Confirmed for 2.5.5: "-key size exceeds implementation restriction" @@ -46,18 +57,20 @@ act = isql_act('db', test_script) -expected_stdout = """ - TEST_COL1_IDX_A INDEX ON TEST COMPUTED BY ( substring(col1 from 1 for 169) ) - TEST_COL1_IDX_B INDEX ON TEST COMPUTED BY ( substring(trim( col2 from col1 ) from 1 for 169) ) - TEST_COL2_IDX_A INDEX ON TEST COMPUTED BY ( col2 ) - TEST_COL2_IDX_B INDEX ON TEST COMPUTED BY ( substring(col2 from 1 for 169) ) - TEST_COL3_IDX_A INDEX ON TEST COMPUTED BY ( col3 ) - TEST_COL3_IDX_B INDEX ON TEST COMPUTED BY ( substring(col3 from 1 for 169) ) -""" - -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3') def test_1(act: Action): + + SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + + expected_stdout = f""" + {SCHEMA_PREFIX}TEST_COL1_IDX_A INDEX ON TEST COMPUTED BY ( {IDX_EXPR_1} ) + {SCHEMA_PREFIX}TEST_COL1_IDX_B INDEX ON TEST COMPUTED BY ( {IDX_EXPR_2} ) + {SCHEMA_PREFIX}TEST_COL2_IDX_A INDEX ON TEST COMPUTED BY ( {IDX_EXPR_3} ) + {SCHEMA_PREFIX}TEST_COL2_IDX_B INDEX ON TEST COMPUTED BY ( {IDX_EXPR_4} ) + {SCHEMA_PREFIX}TEST_COL3_IDX_A INDEX ON TEST COMPUTED BY ( {IDX_EXPR_5} ) + {SCHEMA_PREFIX}TEST_COL3_IDX_B INDEX ON TEST COMPUTED BY ( {IDX_EXPR_6} ) + """ + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From fd10f111f237be2458dcd02dd51742127d1b6695 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:45:02 +0300 Subject: [PATCH 0781/1064] Added/Updated tests\bugs\core_3690_dialect_1_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3690_dialect_1_test.py | 29 +++++++++++++++++++------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_3690_dialect_1_test.py b/tests/bugs/core_3690_dialect_1_test.py index 43691247..70b1171d 100644 --- a/tests/bugs/core_3690_dialect_1_test.py +++ b/tests/bugs/core_3690_dialect_1_test.py @@ -7,12 +7,18 @@ DESCRIPTION: SQL dialect 1 allows such queries for backward compatibility reasons JIRA: CORE-3690 FBTEST: bugs.core_3690 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db_1 = db_factory(sql_dialect=1) +db = db_factory(sql_dialect=1) test_script = """ set list on; @@ -20,20 +26,27 @@ select 0*rdb$relation_id as id from rdb$database,rdb$database; """ -act_1 = python_act('db_1') +substitutions = [('[ \t]+', ' ')] +act = python_act('db', substitutions = substitutions) -expected_stdout_1 = """ +expected_stdout_5x = """ MON$SQL_DIALECT 1 - SQL warning code = 204 -Ambiguous field name between table RDB$DATABASE and table RDB$DATABASE -RDB$RELATION_ID + ID 0 +""" +expected_stdout_6x = """ + MON$SQL_DIALECT 1 + SQL warning code = 204 + -Ambiguous field name between table "SYSTEM"."RDB$DATABASE" and table "SYSTEM"."RDB$DATABASE" + -RDB$RELATION_ID ID 0 """ @pytest.mark.version('>=3') -def test_dialect_1(act_1: Action): - act_1.expected_stdout = expected_stdout_1 - act_1.isql(switches=['-q', '-sql_dialect', '1'], input=test_script, combine_output=True) - assert act_1.clean_stdout == act_1.clean_expected_stdout +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q', '-sql_dialect', '1'], input=test_script, combine_output=True) + assert act.clean_stdout == act.clean_expected_stdout From 3138ec742923b28d69c5fb04bb0da9076e8464fc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:48:41 +0300 Subject: [PATCH 0782/1064] Added/Updated tests\bugs\core_3690_dialect_3_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3690_dialect_3_test.py | 37 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_3690_dialect_3_test.py b/tests/bugs/core_3690_dialect_3_test.py index dac2ac49..1374c264 100644 --- a/tests/bugs/core_3690_dialect_3_test.py +++ b/tests/bugs/core_3690_dialect_3_test.py @@ -2,17 +2,23 @@ """ ID: issue-4038 -ISSUE: https://github.com/FirebirdSQL/firebird/issues/4038 +ISSUE: 4038 TITLE: Wrong warning message for ambiguous query -DESCRIPTION: SQL dialect 1 allows such queries for backward compatibility reasons +DESCRIPTION: Check for dialect 3. JIRA: CORE-3690 FBTEST: bugs.core_3690 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db_3 = db_factory(sql_dialect=3) +db = db_factory() test_script = """ set list on; @@ -20,11 +26,11 @@ select 0*rdb$relation_id as id from rdb$database,rdb$database; """ -act_3 = python_act('db_3') - -expected_stdout_3 = """ - MON$SQL_DIALECT 3 +substitutions = [('[ \t]+', ' ')] +act = python_act('db', substitutions = substitutions) +expected_stdout_5x = """ + MON$SQL_DIALECT 3 Statement failed, SQLSTATE = 42702 Dynamic SQL Error -SQL error code = -204 @@ -32,8 +38,17 @@ -RDB$RELATION_ID """ +expected_stdout_6x = """ + MON$SQL_DIALECT 3 + Statement failed, SQLSTATE = 42702 + Dynamic SQL Error + -SQL error code = -204 + -Ambiguous field name between table "SYSTEM"."RDB$DATABASE" and table "SYSTEM"."RDB$DATABASE" + -RDB$RELATION_ID +""" + @pytest.mark.version('>=3') -def test_dialect_3(act_3: Action): - act_3.expected_stdout = expected_stdout_3 - act_3.isql(switches=['-q', '-sql_dialect', '3'], input=test_script, combine_output=True) - assert act_3.clean_stdout == act_3.clean_expected_stdout +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], input=test_script, combine_output=True) + assert act.clean_stdout == act.clean_expected_stdout From a42384df40f1811e955526982353dd21dd73a516 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 27 Jun 2025 23:51:22 +0300 Subject: [PATCH 0783/1064] Added/Updated tests\bugs\core_3691_test.py: Added 'SCHEMA_PREFIX' to be substituted in expected_out on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3691_test.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_3691_test.py b/tests/bugs/core_3691_test.py index 2af895f9..680e16bd 100644 --- a/tests/bugs/core_3691_test.py +++ b/tests/bugs/core_3691_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-3691 FBTEST: bugs.core_3691 +NOTES: + [27.06.2025] pzotov + Added 'SCHEMA_PREFIX' to be substituted in expected_out on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,16 +33,19 @@ act = isql_act('db', test_script) -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - violation of FOREIGN KEY constraint "TDETL_FK" on table "TDETL" - -Foreign key reference target does not exist - -Problematic key value is ("PID" = 2) -""" - @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "TDETL_FK" on table {SCHEMA_PREFIX}"TDETL" + -Foreign key reference target does not exist + -Problematic key value is ("PID" = 2) + """ + + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 6e6c3460c583f1d1e68fc5bc3acf5646629bc1f2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 12:59:07 +0300 Subject: [PATCH 0784/1064] Added/Updated tests\bugs\core_3722_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3722_test.py | 49 +++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_3722_test.py b/tests/bugs/core_3722_test.py index a02a4a1c..e529a61a 100644 --- a/tests/bugs/core_3722_test.py +++ b/tests/bugs/core_3722_test.py @@ -7,36 +7,49 @@ DESCRIPTION: JIRA: CORE-3722 FBTEST: bugs.core_3722 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (a varchar(5)); -create index t_a on t (a); +db = db_factory() + +test_script = """ + create table test (f01 int); + insert into test select iif(rand() < 0.5, null, rand()*1000) from rdb$types; + commit; + create index test_f01 on test (f01); + set planonly; + select * from test where f01 is null; + select * from test where f01 is not distinct from null; + select * from test where f01 is not distinct from null PLAN (test INDEX (test_f01)); + select * from test where f01 is not distinct from nullif('', ''); """ -db = db_factory(init=init_script) +act = isql_act('db', test_script) -test_script = """SET PLAN ON; -select * from t where a is null; -select * from t where a is not distinct from null; -select * from t where a is not distinct from null PLAN (T INDEX (T_A)); -select * from t where a is not distinct from nullif('', ''); +expected_stdout_5x = """ + PLAN (TEST INDEX (TEST_F01)) + PLAN (TEST INDEX (TEST_F01)) + PLAN (TEST INDEX (TEST_F01)) + PLAN (TEST INDEX (TEST_F01)) """ -act = isql_act('db', test_script) - -expected_stdout = """ -PLAN (T INDEX (T_A)) -PLAN (T INDEX (T_A)) -PLAN (T INDEX (T_A)) -PLAN (T INDEX (T_A)) +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01")) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 786b81e7022caba81c7e576fc528132db58d86bc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 13:13:13 +0300 Subject: [PATCH 0785/1064] Added/Updated tests\bugs\core_3735_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3735_test.py | 392 ++++++++++++++++++++--------------- 1 file changed, 229 insertions(+), 163 deletions(-) diff --git a/tests/bugs/core_3735_test.py b/tests/bugs/core_3735_test.py index a73a9566..142e2dba 100644 --- a/tests/bugs/core_3735_test.py +++ b/tests/bugs/core_3735_test.py @@ -7,173 +7,239 @@ DESCRIPTION: JIRA: CORE-3735 FBTEST: bugs.core_3735 +NOTES: + [28.06.2025] pzotov + Reimplemented: use variables to be used (via f-notations) in expected_out_* instead of hard-coding. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('-Effective user is.*', ''), ('Rolling back work.', ''), - ('Commit current transaction \\(y/n\\)\\?', '')] - db = db_factory() -test_user = user_factory('db', name='tmp$c3735', password='123') - -test_script = """ - -- See also more complex test in CORE-4731 // Prohibit an ability to issue DML or DDL statements on RDB$ tables - - connect '$(DSN)' user tmp$c3735 password '123'; - - set list on; - set blob all; - select current_user from rdb$database; - show grants; - set count on; - - insert into rdb$character_sets( - rdb$character_set_name - ,rdb$form_of_use - ,rdb$number_of_characters - ,rdb$default_collate_name - ,rdb$character_set_id - ,rdb$system_flag - ,rdb$description - ,rdb$function_name - ,rdb$bytes_per_character - )values ( - 'ISO-8859-15', - null, - null, - 'ISO-8859-15', - ( select max(rdb$character_set_id) from rdb$character_sets ) + 1, - 1, - null, - null, - 1 - ) returning - rdb$character_set_name, - rdb$character_set_id, - rdb$default_collate_name - ; - - insert into rdb$collations( - rdb$collation_name - ,rdb$collation_id - ,rdb$character_set_id - ,rdb$collation_attributes - ,rdb$system_flag - ,rdb$description - ,rdb$function_name - ,rdb$base_collation_name - ,rdb$specific_attributes - ) values( - 'SUPER_SMART_ORDER' - ,( select max(rdb$collation_id) from rdb$collations ) + 1 - ,( select rdb$character_set_id from rdb$character_sets where upper(rdb$character_set_name) = upper('ISO-8859-15') ) - ,1 - ,1 - ,null - ,null - ,null - ,null - ) returning - rdb$collation_name - ,rdb$collation_id - ,rdb$character_set_id - ; - - - insert into rdb$database( - rdb$description - ,rdb$relation_id - ,rdb$security_class - ,rdb$character_set_name - ) values ( - 'This is special record, do not delete it!' - ,( select max(rdb$relation_id) from rdb$relations ) + 1 - ,null - ,'ISO_HE_HE' - ) returning - rdb$description - ,rdb$relation_id - ,rdb$security_class - ,rdb$character_set_name - ; - - - update rdb$collations set rdb$description = null rows 1 - returning - rdb$collation_id - ; - - update rdb$character_sets set rdb$description = null rows 1 - returning - rdb$character_set_id - ; - - update rdb$database set rdb$character_set_name = 'ISO_HA_HA' - returning - rdb$relation_id - ; - - delete from rdb$collations order by rdb$collation_id desc rows 1 - returning - rdb$collation_name - ,rdb$collation_id - ,rdb$character_set_id - ; - - delete from rdb$character_sets order by rdb$character_set_id desc rows 1 - returning - rdb$character_set_name, - rdb$character_set_id, - rdb$default_collate_name - ; - - delete from rdb$database order by rdb$relation_id desc rows 1 - returning - rdb$description - ,rdb$relation_id - ,rdb$security_class - ,rdb$character_set_name - ; - - commit; -""" - -act = isql_act('db', test_script, substitutions=substitutions) - -expected_stdout = """ - USER TMP$C3735 -""" - -expected_stderr = """ - There is no privilege granted in this database - Statement failed, SQLSTATE = 28000 - no permission for INSERT access to TABLE RDB$CHARACTER_SETS - Statement failed, SQLSTATE = 28000 - no permission for INSERT access to TABLE RDB$COLLATIONS - Statement failed, SQLSTATE = 28000 - no permission for INSERT access to TABLE RDB$DATABASE - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$COLLATIONS - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$CHARACTER_SETS - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$DATABASE - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$COLLATIONS - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$CHARACTER_SETS - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$DATABASE -""" - -@pytest.mark.version('>=3.0') -def test_1(act: Action, test_user: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - +tmp_user = user_factory('db', name='tmp$c3735', password='123') + +substitutions = [('[ \t]+', ' '), ('/\\* Grant permissions for.*','')] + +act = isql_act('db', substitutions=substitutions) + +@pytest.mark.version('>=3') +def test_1(act: Action, tmp_user: User): + + test_script = f""" + -- See also more complex test in CORE-4731 // Prohibit an ability to issue DML or DDL statements on RDB$ tables + + connect '{act.db.dsn}' user '{tmp_user.name}' password '{tmp_user.password}'; + + set list on; + set blob all; + select current_user from rdb$database; + show grants; + set count on; + + insert into rdb$character_sets( + rdb$character_set_name + ,rdb$form_of_use + ,rdb$number_of_characters + ,rdb$default_collate_name + ,rdb$character_set_id + ,rdb$system_flag + ,rdb$description + ,rdb$function_name + ,rdb$bytes_per_character + )values ( + 'ISO-8859-15', + null, + null, + 'ISO-8859-15', + ( select max(rdb$character_set_id) from rdb$character_sets ) + 1, + 1, + null, + null, + 1 + ) returning + rdb$character_set_name, + rdb$character_set_id, + rdb$default_collate_name + ; + + insert into rdb$collations( + rdb$collation_name + ,rdb$collation_id + ,rdb$character_set_id + ,rdb$collation_attributes + ,rdb$system_flag + ,rdb$description + ,rdb$function_name + ,rdb$base_collation_name + ,rdb$specific_attributes + ) values( + 'SUPER_SMART_ORDER' + ,( select max(rdb$collation_id) from rdb$collations ) + 1 + ,( select rdb$character_set_id from rdb$character_sets where upper(rdb$character_set_name) = upper('ISO-8859-15') ) + ,1 + ,1 + ,null + ,null + ,null + ,null + ) returning + rdb$collation_name + ,rdb$collation_id + ,rdb$character_set_id + ; + + + insert into rdb$database( + rdb$description + ,rdb$relation_id + ,rdb$security_class + ,rdb$character_set_name + ) values ( + 'This is special record, do not delete it!' + ,( select max(rdb$relation_id) from rdb$relations ) + 1 + ,null + ,'ISO_HE_HE' + ) returning + rdb$description + ,rdb$relation_id + ,rdb$security_class + ,rdb$character_set_name + ; + + + update rdb$collations set rdb$description = null rows 1 + returning + rdb$collation_id + ; + + update rdb$character_sets set rdb$description = null rows 1 + returning + rdb$character_set_id + ; + + update rdb$database set rdb$character_set_name = 'ISO_HA_HA' + returning + rdb$relation_id + ; + + delete from rdb$collations order by rdb$collation_id desc rows 1 + returning + rdb$collation_name + ,rdb$collation_id + ,rdb$character_set_id + ; + + delete from rdb$character_sets order by rdb$character_set_id desc rows 1 + returning + rdb$character_set_name, + rdb$character_set_id, + rdb$default_collate_name + ; + + delete from rdb$database order by rdb$relation_id desc rows 1 + returning + rdb$description + ,rdb$relation_id + ,rdb$security_class + ,rdb$character_set_name + ; + + commit; + """ + + expected_stdout_3x = f""" + USER {tmp_user.name.upper()} + There is no privilege granted in this database + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$CHARACTER_SETS + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$COLLATIONS + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$DATABASE + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$COLLATIONS + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$CHARACTER_SETS + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$COLLATIONS + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$CHARACTER_SETS + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$DATABASE + """ + + expected_stdout_5x = f""" + USER {tmp_user.name.upper()} + There is no privilege granted in this database + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$CHARACTER_SETS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$COLLATIONS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$COLLATIONS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$CHARACTER_SETS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$COLLATIONS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$CHARACTER_SETS + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} + """ + + expected_stdout_6x = f""" + USER {tmp_user.name.upper()} + + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE "SYSTEM"."RDB$CHARACTER_SETS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE "SYSTEM"."RDB$COLLATIONS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE "SYSTEM"."RDB$DATABASE" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE "SYSTEM"."RDB$COLLATIONS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE "SYSTEM"."RDB$CHARACTER_SETS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE "SYSTEM"."RDB$DATABASE" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE "SYSTEM"."RDB$COLLATIONS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE "SYSTEM"."RDB$CHARACTER_SETS" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE "SYSTEM"."RDB$DATABASE" + -Effective user is {tmp_user.name.upper()} + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], connect_db = False, input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0b0db13b913659bce856c31dc5d118acbe3749c9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 14:08:05 +0300 Subject: [PATCH 0786/1064] Added/Updated tests\bugs\core_3736_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3736_test.py | 123 ++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 47 deletions(-) diff --git a/tests/bugs/core_3736_test.py b/tests/bugs/core_3736_test.py index 0ea3ed70..787c2a58 100644 --- a/tests/bugs/core_3736_test.py +++ b/tests/bugs/core_3736_test.py @@ -8,6 +8,15 @@ DESCRIPTION: JIRA: CORE-3736 FBTEST: bugs.core_3736 +NOTES: + [28.06.2025] pzotov + Reimplemented: use variables to be used (via f-notations) in expected_out_* instead of hard-coding. + Only error messages are checked in this test (rather than both stdout and stderr). + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,8 +27,12 @@ user_1_ro = user_factory('db', name='tmp$c3736_ro', password='tmp$c3736_ro') user_1_ud = user_factory('db', name='tmp$c3736_ud', password='tmp$c3736_ud') -test_script = """ +READ_ONLY_STTM = "select current_user, 'select_read_only', id from t_read_only_for_non_sys" +WITH_LOCK_STTM = "select current_user, 'select_with_lock', id from t_read_only_for_non_sys for update with lock" + +test_script = f""" set wng off; + set list on; recreate table t_read_only_for_non_sys(id int); commit; @@ -52,7 +65,7 @@ into v_dbname; for - execute statement 'select current_user, ''select_read_only'', id from t_read_only_for_non_sys' -- for update with lock' + execute statement q'#{READ_ONLY_STTM}#' on external (v_dbname) as user (v_usr_ro) password (v_pwd_ro) into who_am_i, my_action, what_i_see @@ -60,7 +73,7 @@ suspend; for - execute statement 'select current_user, ''select_with_lock'', id from t_read_only_for_non_sys for update with lock' + execute statement q'#{WITH_LOCK_STTM}#' on external (v_dbname) as user (v_usr_ro) password (v_pwd_ro) into who_am_i, my_action, what_i_see @@ -90,7 +103,7 @@ into v_dbname; for - execute statement 'select current_user, ''select_with_lock'', id from t_read_only_for_non_sys for update with lock' + execute statement q'#{WITH_LOCK_STTM}#' on external (v_dbname) as user (v_usr_ud) password (v_pwd_ud) into who_am_i, my_action, what_i_see @@ -101,54 +114,70 @@ ^ set term ;^ rollback; - - -- |||||||||||||||||||||||||||| - -- ###################################||| FB 4.0+, SS and SC |||############################## - -- |||||||||||||||||||||||||||| - -- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current - -- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility - -- will not able to drop this database at the final point of test. - -- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this - -- we have to wait for seconds after it (discussion and small test see - -- in the letter to hvlad and dimitr 13.10.2019 11:10). - -- This means that one need to kill all connections to prevent from exception on cleanup phase: - -- SQLCODE: -901 / lock time-out on wait transaction / object is in use - -- ############################################################################################# - delete from mon$attachments where mon$attachment_id != current_connection; - commit; """ -act = isql_act('db', test_script, - substitutions=[('^((?!335544352|335544878).)*$', ''), ('number is.*', '')]) +# Only error messages are checked in this test: +substitutions = [ ('(-)?At block line(:)?\\s+\\d+.*', ''), + ('Data source : Firebird::.*', 'Data source : Firebird::'), + ('335544878 : concurrent transaction number.*', '335544878 : concurrent transaction number'), + ] -expected_stdout = """ - WHO_AM_I MY_ACTION WHAT_I_SEE - =============================== ==================== ============ - TMP$C3736_RO select_read_only 1 - TMP$C3736_RO select_read_only 2 - TMP$C3736_RO select_read_only 3 - TMP$C3736_RO select_read_only 4 - TMP$C3736_RO select_read_only 5 - - - WHO_AM_I MY_ACTION WHAT_I_SEE - =============================== ==================== ============ - TMP$C3736_UD select_with_lock 1 - TMP$C3736_UD select_with_lock 2 - TMP$C3736_UD select_with_lock 3 -""" - -expected_stderr = """ - 335544352 : no permission for UPDATE access to TABLE T_READ_ONLY_FOR_NON_SYS - 335544878 : concurrent transaction number is 806 -""" +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.es_eds @pytest.mark.version('>=3.0') def test_1(act: Action, user_1_ro: User, user_1_ud: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + expected_stderr_3x = f""" + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544352 : no permission for UPDATE access to TABLE T_READ_ONLY_FOR_NON_SYS + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_fetch : + 335544336 : deadlock + 335544451 : update conflicts with concurrent update + 335544878 : concurrent transaction number + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + """ + + expected_stderr_5x = f""" + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544352 : no permission for UPDATE access to TABLE T_READ_ONLY_FOR_NON_SYS + 335545254 : Effective user is {user_1_ro.name.upper()} + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_fetch : + 335544336 : deadlock + 335544451 : update conflicts with concurrent update + 335544878 : concurrent transaction number + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + """ + + expected_stderr_6x = f""" + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_prepare : + 335544352 : no permission for UPDATE access to TABLE "PUBLIC"."T_READ_ONLY_FOR_NON_SYS" + 335545254 : Effective user is {user_1_ro.name.upper()} + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + + Statement failed, SQLSTATE = 42000 + Execute statement error at isc_dsql_fetch : + 335544336 : deadlock + 335544451 : update conflicts with concurrent update + 335544878 : concurrent transaction number + Statement : {WITH_LOCK_STTM} + Data source : Firebird:: + """ + + act.expected_stderr = expected_stderr_3x if act.is_version('<4') else expected_stderr_5x if act.is_version('<6') else expected_stderr_6x + act.execute(combine_output = False) # ::: NB ::: we need to parse only error messages. + assert act.clean_stderr == act.clean_expected_stderr From 8ac9f1523f006be9979dae60636c7c12c1f76d0a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 14:12:25 +0300 Subject: [PATCH 0787/1064] Added/Updated tests\bugs\core_3761_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3761_test.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_3761_test.py b/tests/bugs/core_3761_test.py index 0482e531..d72511ee 100644 --- a/tests/bugs/core_3761_test.py +++ b/tests/bugs/core_3761_test.py @@ -9,20 +9,24 @@ FBTEST: bugs.core_3761 NOTES: [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). + Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate + delimiters without any statements between them (two semicolon, two carets etc). + + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - create exception check_exception 'check exception'; - commit; -""" - -db = db_factory(init=init_script) +db = db_factory() test_script = """ + create exception check_exception 'check exception'; + commit; set term ^; execute block as begin @@ -31,19 +35,24 @@ set term ;^ """ -act = isql_act('db', test_script, substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) +act = isql_act('db', test_script, substitutions=[('(-)?At block line(:)?\\s+\\d+.*', '')]) -expected_stdout = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 exception 1 -CHECK_EXCEPTION -word - -At block line: 4, col: 2 """ -@pytest.mark.version('>=3') +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."CHECK_EXCEPTION" + -word +""" + +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From ebe9054bc9c41fb00026ace9a7171f5a7c774e24 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:11:41 +0300 Subject: [PATCH 0788/1064] Added/Updated tests\bugs\core_3834_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3834_test.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3834_test.py b/tests/bugs/core_3834_test.py index 2668ec10..581abd8c 100644 --- a/tests/bugs/core_3834_test.py +++ b/tests/bugs/core_3834_test.py @@ -14,6 +14,11 @@ 2. FB 5.0.0.455 and later: data sources with equal cardinality now present in the HASH plan in order they are specified in the query. Reversed order was used before this build. Because of this, two cases of expected stdout must be taken in account, see variables 'fb3x_checked_stdout' and 'fb5x_checked_stdout'. + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -25,22 +30,29 @@ set list on; set planonly; -- This query caused FB 2.5.0 to crash: - select * from (select * from mon$attachments a) a natural join mon$statements s where mon$stat_id = ?; + select * + from (select * from mon$attachments a_mon_att_inner) + a_mon_att_outer natural join mon$statements a_mon_sttm + where a_mon_sttm.mon$stat_id = ?; quit; """ act = isql_act('db', test_script) fb3x_checked_stdout = """ - PLAN HASH (S NATURAL, A A NATURAL) + PLAN HASH (A_MON_STTM NATURAL, A_MON_ATT_OUTER A_MON_ATT_INNER NATURAL) """ fb5x_checked_stdout = """ - PLAN HASH (A A NATURAL, S NATURAL) + PLAN HASH (A_MON_ATT_OUTER A_MON_ATT_INNER NATURAL, A_MON_STTM NATURAL) +""" + +fb6x_checked_stdout = """ + PLAN HASH ("A_MON_ATT_OUTER" "A_MON_ATT_INNER" NATURAL, "A_MON_STTM" NATURAL) """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout + act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout act.execute() assert act.clean_stdout == act.clean_expected_stdout From bd9137e7f909efdb1ef6614c61dc7b12ac8fc3cf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:15:39 +0300 Subject: [PATCH 0789/1064] Added/Updated tests\bugs\core_3881_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3881_test.py | 48 +++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_3881_test.py b/tests/bugs/core_3881_test.py index cf7bd6e1..adf83589 100644 --- a/tests/bugs/core_3881_test.py +++ b/tests/bugs/core_3881_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-3881 FBTEST: bugs.core_3881 +NOTES: + [27.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -52,31 +56,35 @@ act = isql_act('db', test_script, substitutions=[('-At trigger.*', '')]) -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TMAIN_PK" on table "TMAIN" - -Problematic key value is ("ID" = 300) - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TMAIN_MKA_MKB_CONSTRAINT_UNQ" on table "TMAIN" - -Problematic key value is ("MKA" = NULL, "MKB" = 200) +@pytest.mark.version('>=3') +def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' - Statement failed, SQLSTATE = 23000 - attempt to store duplicate value (visible to active transactions) in unique index "TMAIN_DIFFERENCE_UNQ_IDX" - -Problematic key value is ( = 0) + expected_stderr = f""" + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TMAIN_PK" on table {SQL_SCHEMA_PREFIX}"TMAIN" + -Problematic key value is ("ID" = 300) - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TMAIN_MKA_MKB_CONSTRAINT_UNQ" on table "TMAIN" - -Problematic key value is ("MKA" = 200, "MKB" = 200) + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TMAIN_MKA_MKB_CONSTRAINT_UNQ" on table {SQL_SCHEMA_PREFIX}"TMAIN" + -Problematic key value is ("MKA" = NULL, "MKB" = 200) - Statement failed, SQLSTATE = 23000 - attempt to store duplicate value (visible to active transactions) in unique index "TMAIN_DIFFERENCE_UNQ_IDX" - -Problematic key value is ( = 0) - -At trigger 'CHECK_2' -""" + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index {SQL_SCHEMA_PREFIX}"TMAIN_DIFFERENCE_UNQ_IDX" + -Problematic key value is ( = 0) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TMAIN_MKA_MKB_CONSTRAINT_UNQ" on table {SQL_SCHEMA_PREFIX}"TMAIN" + -Problematic key value is ("MKA" = 200, "MKB" = 200) + + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index {SQL_SCHEMA_PREFIX}"TMAIN_DIFFERENCE_UNQ_IDX" + -Problematic key value is ( = 0) + -At trigger 'CHECK_2' + """ -@pytest.mark.version('>=3') -def test_1(act: Action): act.expected_stderr = expected_stderr act.execute() assert act.clean_stderr == act.clean_expected_stderr From 188759fd70d9022dc081af8319f746b7f4041cec Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:22:16 +0300 Subject: [PATCH 0790/1064] Added/Updated tests\bugs\core_3894_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3894_test.py | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_3894_test.py b/tests/bugs/core_3894_test.py index bb933014..6aed46b2 100644 --- a/tests/bugs/core_3894_test.py +++ b/tests/bugs/core_3894_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3894 FBTEST: bugs.core_3894 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -30,25 +36,29 @@ show table test; """ -act = isql_act('db', test_script) +substitutions=[('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE TEST failed + -New size specified for column S01 must be at least 8190 characters. ID INTEGER Nullable S01 VARCHAR(8190) CHARACTER SET UTF8 Nullable """ - -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -ALTER TABLE TEST failed - -New size specified for column S01 must be at least 8190 characters. + -ALTER TABLE "PUBLIC"."TEST" failed + -New size specified for column "S01" must be at least 8190 characters. + Table: PUBLIC.TEST + ID INTEGER Nullable + S01 VARCHAR(8190) CHARACTER SET SYSTEM.UTF8 Nullable """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From c40d59f4a372014cc8a3d307e7cc70e82aa07656 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:26:59 +0300 Subject: [PATCH 0791/1064] Added/Updated tests\bugs\core_3902_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3902_test.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_3902_test.py b/tests/bugs/core_3902_test.py index 86b95304..8f3372d1 100644 --- a/tests/bugs/core_3902_test.py +++ b/tests/bugs/core_3902_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-3902 FBTEST: bugs.core_3902 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -28,16 +34,20 @@ """ -act = isql_act('db', test_script) +substitutions = [(r'RDB\$INDEX_\d+', 'RDB$INDEX_*')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ -PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) -PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) +expected_stdout_5x = """ + PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) + PLAN JOIN (RDB$DATABASE NATURAL, TEMP RDB$RELATIONS INDEX (RDB$INDEX_1)) +""" +expected_stdout_6x = """ + PLAN JOIN ("SYSTEM"."RDB$DATABASE" NATURAL, "TEMP" "SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."RDB$INDEX_1")) + PLAN JOIN ("SYSTEM"."RDB$DATABASE" NATURAL, "TEMP" "SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."RDB$INDEX_1")) """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 13d76d7d4cacc3afbce259fb758167fcda8df739 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:29:33 +0300 Subject: [PATCH 0792/1064] Added/Updated tests\bugs\core_3925_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3925_test.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_3925_test.py b/tests/bugs/core_3925_test.py index c93dd342..1eba387c 100644 --- a/tests/bugs/core_3925_test.py +++ b/tests/bugs/core_3925_test.py @@ -10,6 +10,10 @@ DELETE statement does not raise error. JIRA: CORE-3925 FBTEST: bugs.core_3925 +NOTES: + [27.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -28,16 +32,18 @@ act = isql_act('db', test_script) -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - violation of FOREIGN KEY constraint "FK_KEY_REF" on table "TEST" - -Foreign key reference target does not exist - -Problematic key value is ("REF" = -1) -""" - @pytest.mark.version('>=3.0.5') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "FK_KEY_REF" on table {SQL_SCHEMA_PREFIX}"TEST" + -Foreign key reference target does not exist + -Problematic key value is ("REF" = -1) + """ + + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From dfaa7dbe9bb8d68ad38cf5273ac89a17cc6152e1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:31:46 +0300 Subject: [PATCH 0793/1064] Added/Updated tests\bugs\core_3947_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3947_test.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3947_test.py b/tests/bugs/core_3947_test.py index b59cd3f5..2e581dea 100644 --- a/tests/bugs/core_3947_test.py +++ b/tests/bugs/core_3947_test.py @@ -9,6 +9,12 @@ not be usable for ORDER, only for lookups. JIRA: CORE-3947 FBTEST: bugs.core_3947 +NOTES: + [27.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -45,16 +51,22 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (T ORDER T_S1_NON_UNQ) PLAN SORT (T NATURAL) PLAN SORT (T NATURAL) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" ORDER "PUBLIC"."T_S1_NON_UNQ") + PLAN SORT ("PUBLIC"."T" NATURAL) + PLAN SORT ("PUBLIC"."T" NATURAL) +""" + @pytest.mark.intl @pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 492c70f83cfa863eabca2adc9eef7f2bce98d680 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:33:21 +0300 Subject: [PATCH 0794/1064] Added/Updated tests\bugs\core_3947_test.py: removed duplicated mark --- tests/bugs/core_3947_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/bugs/core_3947_test.py b/tests/bugs/core_3947_test.py index 2e581dea..5af76c77 100644 --- a/tests/bugs/core_3947_test.py +++ b/tests/bugs/core_3947_test.py @@ -65,7 +65,6 @@ @pytest.mark.intl @pytest.mark.version('>=3.0') -@pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) From d381a38208fd84c88e54fd26e564bff0495e14b3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:35:34 +0300 Subject: [PATCH 0795/1064] Added/Updated tests\bugs\core_3963_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3963_test.py | 74 ++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/tests/bugs/core_3963_test.py b/tests/bugs/core_3963_test.py index 4eae7d47..f82d7a6c 100644 --- a/tests/bugs/core_3963_test.py +++ b/tests/bugs/core_3963_test.py @@ -17,6 +17,12 @@ in UDR library "udf_compat", see it in folder: ../plugins/udr/ JIRA: CORE-3963 FBTEST: bugs.core_3963 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -106,6 +112,7 @@ def test_1(act_1: Action): assert (act_1.clean_stderr == act_1.clean_expected_stderr and act_1.clean_stdout == act_1.clean_expected_stdout) +############################################################################# # version: 4.0 test_script_2 = """ @@ -170,53 +177,64 @@ def test_1(act_1: Action): act_2 = isql_act('db', test_script_2) -expected_stdout_2 = """ - +expected_stdout_5x = """ INPUT message field count: 0 - OUTPUT message field count: 1 01: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 - : name: THE_FRAC alias: THE_FRAC - : table: owner: - + : name: THE_FRAC alias: THE_FRAC + : table: owner: THE_FRAC -0.1415926535897931 - - - + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE FUNCTION THE_FRAC failed + -Function THE_FRAC already exists + Statement failed, SQLSTATE = 39000 + Dynamic SQL Error + -SQL error code = -804 + -Function unknown + -THE_FRAC INPUT message field count: 0 - OUTPUT message field count: 1 01: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 - : name: THE_FRAC alias: THE_FRAC - : table: owner: - + : name: THE_FRAC alias: THE_FRAC + : table: owner: THE_FRAC -0.1415926535897931 - -""" - -expected_stderr_2 = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -CREATE FUNCTION THE_FRAC failed -Function THE_FRAC already exists +""" +expected_stdout_6x = """ + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + : name: THE_FRAC alias: THE_FRAC + : table: schema: owner: + THE_FRAC -0.1415926535897931 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE FUNCTION "PUBLIC"."THE_FRAC" failed + -Function "PUBLIC"."THE_FRAC" already exists Statement failed, SQLSTATE = 39000 Dynamic SQL Error -SQL error code = -804 -Function unknown - -THE_FRAC - + -"THE_FRAC" + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + : name: THE_FRAC alias: THE_FRAC + : table: schema: owner: + THE_FRAC -0.1415926535897931 Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -CREATE FUNCTION THE_FRAC failed - -Function THE_FRAC already exists + -CREATE FUNCTION "PUBLIC"."THE_FRAC" failed + -Function "PUBLIC"."THE_FRAC" already exists """ @pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stdout = expected_stdout_2 - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert (act_2.clean_stderr == act_2.clean_expected_stderr and - act_2.clean_stdout == act_2.clean_expected_stdout) - +def test_1(act_2: Action): + act_2.expected_stdout = expected_stdout_5x if act_2.is_version('<6') else expected_stdout_6x + act_2.execute(combine_output = True) + assert act_2.clean_stdout == act_2.clean_expected_stdout From b639f76dd930eb25c33b1a345f20ac18a11d6771 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:41:59 +0300 Subject: [PATCH 0796/1064] Added/Updated tests\bugs\core_3973_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3973_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_3973_test.py b/tests/bugs/core_3973_test.py index 9934bb8c..06dff321 100644 --- a/tests/bugs/core_3973_test.py +++ b/tests/bugs/core_3973_test.py @@ -9,9 +9,13 @@ FBTEST: bugs.core_3973 NOTES: [11.12.2023] pzotov - Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern - ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). - Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern + ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). + Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,14 +36,20 @@ @pytest.mark.version('>=3.0') def test_1(act: Action): - expected_stdout = f""" + expected_stdout_5x = f""" : name: RDB$RELATION_ID alias: R_ID : table: RDB$DATABASE owner: {act.db.user.upper()} : name: RDB$CHARACTER_SET_NAME alias: RDB$CHARACTER_SET_NAME : table: RDB$DATABASE owner: {act.db.user.upper()} """ - act.expected_stdout = expected_stdout + expected_stdout_6x = f""" + : name: RDB$RELATION_ID alias: R_ID + : table: RDB$DATABASE schema: SYSTEM owner: {act.db.user.upper()} + : name: RDB$CHARACTER_SET_NAME alias: RDB$CHARACTER_SET_NAME + : table: RDB$DATABASE schema: SYSTEM owner: {act.db.user.upper()} + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 7141dd211cbf71e249b0659d1114b8f87e71c019 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 15:44:14 +0300 Subject: [PATCH 0797/1064] Added/Updated tests\bugs\core_3997_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3997_test.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_3997_test.py b/tests/bugs/core_3997_test.py index 5ec91183..28176302 100644 --- a/tests/bugs/core_3997_test.py +++ b/tests/bugs/core_3997_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-3997 FBTEST: bugs.core_3997 + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -43,13 +47,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (T_KEY NATURAL, T INDEX ()) """ +expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."T_KEY" NATURAL, "PUBLIC"."T" INDEX ()) +""" + @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From e14d330ebc5ce0edd6fea01da6fdc7c49e821686 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 20:18:51 +0300 Subject: [PATCH 0798/1064] Added/Updated tests\bugs\core_3997_test.py: fixed wrong header --- tests/bugs/core_3997_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_3997_test.py b/tests/bugs/core_3997_test.py index 28176302..a961f93c 100644 --- a/tests/bugs/core_3997_test.py +++ b/tests/bugs/core_3997_test.py @@ -7,6 +7,7 @@ DESCRIPTION: JIRA: CORE-3997 FBTEST: bugs.core_3997 +NOTES: [28.06.2025] pzotov Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. From 554c9ff25b19d3c4117dd06d7eff09fbd39206c2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 20:20:53 +0300 Subject: [PATCH 0799/1064] Added/Updated tests\bugs\core_4027_test.py: Replaced 'SHOW' command with query to RDB tables. Bug still can be seen in 2.5.9.27156. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4027_test.py | 100 ++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/tests/bugs/core_4027_test.py b/tests/bugs/core_4027_test.py index 1c8f3b76..9d902330 100644 --- a/tests/bugs/core_4027_test.py +++ b/tests/bugs/core_4027_test.py @@ -7,6 +7,10 @@ DESCRIPTION: Broken output in ISQL command SHOW TABLE for computed-by field(s). JIRA: CORE-4027 FBTEST: bugs.core_4027 +NOTES: + [28.06.2025] pzotov + Replaced 'SHOW' command with query to RDB tables. Bug still can be seen in 2.5.9.27156. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,7 +18,28 @@ db = db_factory() -test_script = """ +COMPUTED_EXPR_1 = """ + ( + select first 1 t.po_number + from turnovers t + where t.agent_id=test.agent_id + order by t.order_date + ) +""" + +COMPUTED_EXPR_2 = """ + ( + select agent_name + from contragents a + where a.agent_id = test.agent_id + ) +""" + +test_script = f""" + set list on; + set blob all; + set count on; + -- NB: fixed only in 3.0 (checked 30.03.2015) recreate table test (id int); commit; @@ -34,50 +59,53 @@ recreate table test ( agent_id integer not null, - first_po_number computed by ( - ( - select first 1 t.po_number - from turnovers t - where t.agent_id=test.agent_id - order by t.order_date - ) - ), - agent_name computed by ( - ( - select agent_name - from contragents a - where a.agent_id = test.agent_id - ) - ) + first_po_number computed by ( {COMPUTED_EXPR_1} ), + agent_name computed by ( {COMPUTED_EXPR_2} ) ); commit; - show table test; + + select + rf.rdb$field_name fld_name + ,f.rdb$field_type fld_type + ,f.rdb$field_length fld_length + ,f.rdb$field_scale fld_scale + ,f.rdb$computed_source as rdb_blob_id + from rdb$relation_fields rf + left join rdb$fields f on rf.rdb$field_source = f.rdb$field_name + where rf.rdb$relation_name = 'TEST'; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' '), ('RDB_BLOB_ID.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - AGENT_ID INTEGER Not Null - FIRST_PO_NUMBER Computed by: ( - ( - select first 1 t.po_number - from turnovers t - where t.agent_id=test.agent_id - order by t.order_date - ) - ) - AGENT_NAME Computed by: ( - ( - select agent_name - from contragents a - where a.agent_id = test.agent_id - ) - ) +expected_stdout = f""" + FLD_NAME AGENT_ID + FLD_TYPE 8 + FLD_LENGTH 4 + FLD_SCALE 0 + RDB_BLOB_ID + FLD_NAME FIRST_PO_NUMBER + FLD_TYPE 14 + FLD_LENGTH 8 + FLD_SCALE 0 + RDB_BLOB_ID 2:1e4 + ( + {COMPUTED_EXPR_1} + ) + FLD_NAME AGENT_NAME + FLD_TYPE 37 + FLD_LENGTH 25 + FLD_SCALE 0 + RDB_BLOB_ID 2:1e6 + ( + {COMPUTED_EXPR_2} + ) + Records affected: 3 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 0631ceb9da0ad5f0e6db55ad45220eae0200e62c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 21:26:09 +0300 Subject: [PATCH 0800/1064] Added/Updated tests\bugs\core_4038_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4038_test.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_4038_test.py b/tests/bugs/core_4038_test.py index 09d83b90..7cd90917 100644 --- a/tests/bugs/core_4038_test.py +++ b/tests/bugs/core_4038_test.py @@ -7,30 +7,41 @@ DESCRIPTION: JIRA: CORE-4038 FBTEST: bugs.core_4038 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (dbkey char(8) character set octets); -create index it on t (dbkey); -""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ + create table t (dbkey char(8) character set octets); + create index it on t (dbkey); -test_script = """SET PLANONLY; -select * from t as t1 - left join t as t2 on t2.dbkey = t1.rdb$db_key; + SET PLANONLY; + select * from t as t1 + left join t as t2 on t2.dbkey = t1.rdb$db_key; """ act = isql_act('db', test_script) -expected_stdout = """PLAN JOIN (T1 NATURAL, T2 INDEX (IT)) +expected_stdout_5x = """ + PLAN JOIN (T1 NATURAL, T2 INDEX (IT)) """ -@pytest.mark.version('>=3') +expected_stdout_6x = """ + PLAN JOIN ("T1" NATURAL, "T2" INDEX ("PUBLIC"."IT")) +""" + +@pytest.mark.intl +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 43e509ad30a9be7ebb1549ba359f49f7f9637591 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 21:34:45 +0300 Subject: [PATCH 0801/1064] Added/Updated tests\bugs\core_4070_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4070_test.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4070_test.py b/tests/bugs/core_4070_test.py index b905f9d9..40e0788a 100644 --- a/tests/bugs/core_4070_test.py +++ b/tests/bugs/core_4070_test.py @@ -3,10 +3,15 @@ """ ID: issue-4398 ISSUE: 4398 -TITLE: NOT-NULL-column can be used as primary key and filled with NULL-values +TITLE: NOT-NULL column can be used as primary key and filled with NULL-values DESCRIPTION: JIRA: CORE-4070 FBTEST: bugs.core_4070 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -21,16 +26,24 @@ act = isql_act('db', test_script) -expected_stderr = """ +act = isql_act('db', test_script) + +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -ALTER TABLE TEST01 failed -Column: UID not defined as NOT NULL - cannot be used in PRIMARY KEY constraint definition """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST01" failed + -Column: "PUBLIC"."UID" not defined as NOT NULL - cannot be used in PRIMARY KEY constraint definition +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 83e39dad14580101811e48f6ba8925e8099eadd7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 21:35:43 +0300 Subject: [PATCH 0802/1064] Removed wrongly assigned marker (dummy copy/paste) --- tests/bugs/core_3312_test.py | 1 - tests/bugs/core_3947_test.py | 1 - tests/bugs/core_4038_test.py | 1 - 3 files changed, 3 deletions(-) diff --git a/tests/bugs/core_3312_test.py b/tests/bugs/core_3312_test.py index 4c0815e1..7dae875d 100644 --- a/tests/bugs/core_3312_test.py +++ b/tests/bugs/core_3312_test.py @@ -50,7 +50,6 @@ PLAN JOIN ("R" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*"), "SC" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*")) """ -@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x diff --git a/tests/bugs/core_3947_test.py b/tests/bugs/core_3947_test.py index 5af76c77..b79e9ba3 100644 --- a/tests/bugs/core_3947_test.py +++ b/tests/bugs/core_3947_test.py @@ -63,7 +63,6 @@ PLAN SORT ("PUBLIC"."T" NATURAL) """ -@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x diff --git a/tests/bugs/core_4038_test.py b/tests/bugs/core_4038_test.py index 7cd90917..e84c7405 100644 --- a/tests/bugs/core_4038_test.py +++ b/tests/bugs/core_4038_test.py @@ -39,7 +39,6 @@ PLAN JOIN ("T1" NATURAL, "T2" INDEX ("PUBLIC"."IT")) """ -@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 3b9fa5fbf644daf8444156d067f31b61e6181976 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 21:47:57 +0300 Subject: [PATCH 0803/1064] Added/Updated tests\bugs\core_4074_test.py: Replaced 'SHOW' command with query to RDB tables. Bug still can be seen in 2.5.9.27156. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4074_test.py | 63 +++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_4074_test.py b/tests/bugs/core_4074_test.py index 9303b99a..6fedaf1a 100644 --- a/tests/bugs/core_4074_test.py +++ b/tests/bugs/core_4074_test.py @@ -7,40 +7,65 @@ DESCRIPTION: JIRA: CORE-4074 FBTEST: bugs.core_4074 +NOTES: + [28.06.2025] pzotov + Replaced 'SHOW' command with query to RDB tables. + See also test for https://github.com/FirebirdSQL/firebird/issues/4357 + Bug still can be seen in 2.5.9.27156 - rdb$computed_source has weird content: + ======= + ( 'fabio ' || position('x','schunig') ), + f02 numeric(8,2) default 0 + ) + ======= + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - recreate table test01 ( - f01 computed by ( 'fabio ' || position('x','schunig') ), +db = db_factory() + +COMPUTED_EXPR = "'fabio ' || position('x','schunig')" +test_script = f""" + set list on; + set blob all; + recreate table test ( + f01 computed by ( {COMPUTED_EXPR} ), f02 numeric(8,2) default 0 ); + commit; + select + rf.rdb$field_name fld_name + ,f.rdb$field_type fld_type + ,f.rdb$field_length fld_length + ,f.rdb$field_scale fld_scale + ,f.rdb$computed_source as rdb_blob_id + from rdb$relation_fields rf + left join rdb$fields f on rf.rdb$field_source = f.rdb$field_name + where rf.rdb$relation_name = upper('TEST'); """ -db = db_factory(init=init_script) - -test_script = """ - show table test01; - -- ::: NB ::: On WI-V2.5.4.26856, 26-mar-2015, output is: - -- F01 Computed by: ( 'fabio ' || position('x','schunig') ), - -- f02 numeric(8,2) default 0 - -- ) - -- F02 NUMERIC(8, 2) Nullable ) - -- (i.e. it DOES contain "strange" last line) -""" - -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' '), ('RDB_BLOB_ID.*', '') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - F01 Computed by: ( 'fabio ' || position('x','schunig') ) - F02 NUMERIC(8, 2) Nullable default 0 + FLD_NAME F01 + FLD_TYPE 37 + FLD_LENGTH 17 + FLD_SCALE 0 + RDB_BLOB_ID 2:1e4 + ( 'fabio ' || position('x','schunig') ) + + FLD_NAME F02 + FLD_TYPE 8 + FLD_LENGTH 4 + FLD_SCALE -2 + RDB_BLOB_ID """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 618491f6269a2e5ffcd17cab6c31dbe74dbf2af0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 21:48:27 +0300 Subject: [PATCH 0804/1064] Added/Updated tests\bugs\core_4027_test.py: Addedcomment - link to probably related test for #4402 --- tests/bugs/core_4027_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_4027_test.py b/tests/bugs/core_4027_test.py index 9d902330..e8d8fc3d 100644 --- a/tests/bugs/core_4027_test.py +++ b/tests/bugs/core_4027_test.py @@ -9,6 +9,7 @@ FBTEST: bugs.core_4027 NOTES: [28.06.2025] pzotov + See also test for https://github.com/FirebirdSQL/firebird/issues/4402 Replaced 'SHOW' command with query to RDB tables. Bug still can be seen in 2.5.9.27156. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ From dd2309e1ef848a2c5abcece955aeb324f95be409 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:00:01 +0300 Subject: [PATCH 0805/1064] Added/Updated tests\bugs\core_4075_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4075_test.py | 79 +++++++++++++++++------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/tests/bugs/core_4075_test.py b/tests/bugs/core_4075_test.py index 2f6ea156..6ade6ec1 100644 --- a/tests/bugs/core_4075_test.py +++ b/tests/bugs/core_4075_test.py @@ -5,25 +5,27 @@ ISSUE: 4403 TITLE: Server bugchecks or crashes on exception in calculated index DESCRIPTION: -NOTES: -[18.10.2016] added test case from #4918 - NB: 2.5.x output contains TWO lines with error message, i.e.: - Statement failed, SQLSTATE = 22018 - conversion error from string "2014.02.33" - -conversion error from string "2014.02.33" - Decided to suppress second line because its unlikely to be fixed - (after get reply from dimitr, letter 18.10.2016 18:47). -[16.09.2017] added separate section for 4.0 because STDERR now - contains name of index that causes problem - this is so after core-5606 - was implemented ("Add expression index name to exception message ...") JIRA: CORE-4075 FBTEST: bugs.core_4075 +NOTES: + [18.10.2016] + Added test case from #4918 + [16.09.2017] + Added separate section for 4.0 because STDERR now contains name of index that causes problem (after core-5606 was implemented) + [27.06.2025] pzotov + Replaced subst: suppress any hyphen sign that occurs at starting position of every error message. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ recreate table TEST (BIT smallint); create index IDX_TEST_BIT on TEST computed by (bin_shl(1, TEST.BIT-1)); @@ -34,56 +36,51 @@ ); create index T_INDEX on T_TABLE computed by (cast(F_YEAR || '.' || F_MONTH_DAY as date)); commit; - - """ - -db = db_factory(init=init_script) - -test_script = """ + insert into test values (0); -- Trace: -- 335544606 : expression evaluation not supported -- 335544967 : Argument for BIN_SHL must be zero or positive - -- from core-4603: insert into T_TABLE (F_YEAR, F_MONTH_DAY) values ('2014', '02.33'); """ -act = isql_act('db', test_script, substitutions=[('-conversion error from string "2014.02.33"', '')]) - -# version: 3 +substitutions = [('^\\s*(-)?', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr_1 = """ +expected_stdout_3x = """ Statement failed, SQLSTATE = 42000 expression evaluation not supported - -Argument for BIN_SHL must be zero or positive + Argument for BIN_SHL must be zero or positive Statement failed, SQLSTATE = 22018 conversion error from string "2014.02.33" """ -@pytest.mark.version('>=3,<4.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr_1 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - -# version: 4.0 - -expected_stderr_2 = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Expression evaluation error for index "IDX_TEST_BIT" on table "TEST" - -expression evaluation not supported - -Argument for BIN_SHL must be zero or positive + expression evaluation not supported + Argument for BIN_SHL must be zero or positive Statement failed, SQLSTATE = 22018 Expression evaluation error for index "T_INDEX" on table "T_TABLE" - -conversion error from string "2014.02.33" + conversion error from string "2014.02.33" """ -@pytest.mark.version('>=4.0') -def test_2(act: Action): - act.expected_stderr = expected_stderr_2 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Expression evaluation error for index ""PUBLIC"."IDX_TEST_BIT"" on table ""PUBLIC"."TEST"" + expression evaluation not supported + Argument for BIN_SHL must be zero or positive + + Statement failed, SQLSTATE = 22018 + Expression evaluation error for index ""PUBLIC"."T_INDEX"" on table ""PUBLIC"."T_TABLE"" + conversion error from string "2014.02.33" +""" +@pytest.mark.version('>=3') +def test_1(act: Action): + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f2a772dc874302b57e8eb5afd5a716539eeead95 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:04:53 +0300 Subject: [PATCH 0806/1064] Added/Updated tests\bugs\core_4084_test.py: Only STDERR must be checked in this test. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4084_test.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4084_test.py b/tests/bugs/core_4084_test.py index 2e73c203..d789f283 100644 --- a/tests/bugs/core_4084_test.py +++ b/tests/bugs/core_4084_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4084 FBTEST: bugs.core_4084 +NOTES: + [28.06.2025] pzotov + Data in STDOUT is irrelevant and may differ in among FB versions. + Only STDERR must be checked in this test. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,7 +21,6 @@ db = db_factory() test_script = """ - set planonly; select iif(d is null, 10, 0) + sys as sys, count(*) @@ -30,14 +35,12 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN (D NATURAL) - PLAN SORT (R NATURAL) +expected_stderr = """ """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout + act.expected_stderr = expected_stderr + act.execute(combine_output = False) # ::: NB ::: Only STDERR is checked in this test! + assert act.clean_stderr == act.clean_expected_stderr From 25b2cb3a6be172cb4906e7d2341edc4995978c15 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:28:03 +0300 Subject: [PATCH 0807/1064] Added/Updated tests\bugs\core_4102_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4102_test.py | 41 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_4102_test.py b/tests/bugs/core_4102_test.py index 16a1973f..907e5a0d 100644 --- a/tests/bugs/core_4102_test.py +++ b/tests/bugs/core_4102_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4102 FBTEST: bugs.core_4102 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,26 +20,33 @@ db = db_factory() -test_script = """SET PLANONLY; -select * from -( - select rdb$relation_id as id - from rdb$relations r - union all - select rdb$relation_id as id - from rdb$relations r -) x -where x.id = 0 or x.id = 1; +test_script = """ + SET PLANONLY; + select * from + ( + select rdb$relation_id as id + from rdb$relations r + union all + select rdb$relation_id as id + from rdb$relations r + ) x + where x.id = 0 or x.id = 1; """ act = isql_act('db', test_script) -expected_stdout = """PLAN (X R INDEX (RDB$INDEX_1, RDB$INDEX_1), X R INDEX (RDB$INDEX_1, RDB$INDEX_1)) +substitutions = [(r'RDB\$INDEX_\d+', 'RDB$INDEX_*')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + PLAN (X R INDEX (RDB$INDEX_*, RDB$INDEX_*), X R INDEX (RDB$INDEX_*, RDB$INDEX_*)) +""" +expected_stdout_6x = """ + PLAN ("X" "R" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*"), "X" "R" INDEX ("SYSTEM"."RDB$INDEX_*", "SYSTEM"."RDB$INDEX_*")) """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 84e8b56a268d3747558341247d9ad18e30694bf0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:31:44 +0300 Subject: [PATCH 0808/1064] Added/Updated tests\bugs\core_4117_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4117_test.py | 38 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4117_test.py b/tests/bugs/core_4117_test.py index 4d073508..5fe18552 100644 --- a/tests/bugs/core_4117_test.py +++ b/tests/bugs/core_4117_test.py @@ -9,6 +9,12 @@ value if this field is not a part of excpression JIRA: CORE-4117 FBTEST: bugs.core_4117 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -79,24 +85,38 @@ update test2 set id = 2; """ -act = isql_act('db', test_script, substitutions=[('line: [0-9]+, col: [0-9]+', '')]) +act = isql_act('db', test_script, substitutions=[('line: \\d+.*', '')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 exception 1 -EX_BAD_COMPUTED_FIELD_VALUE -20 - -At trigger 'TEST1_BU' line: 3, col: 7 + -At trigger 'TEST1_BU' + Statement failed, SQLSTATE = HY000 exception 1 -EX_BAD_COMPUTED_FIELD_VALUE -20 - -At trigger 'TEST2_BU' line: 3, col: 7 + -At trigger 'TEST2_BU' """ -@pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_BAD_COMPUTED_FIELD_VALUE" + -20 + -At trigger "PUBLIC"."TEST1_BU" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_BAD_COMPUTED_FIELD_VALUE" + -20 + -At trigger "PUBLIC"."TEST2_BU" +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f61235b7d298443fc406baa502ada45fc5a97b3e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:36:19 +0300 Subject: [PATCH 0809/1064] Added/Updated tests\bugs\core_4118_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4118_test.py | 39 ++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_4118_test.py b/tests/bugs/core_4118_test.py index 7988fc6b..b5c13b39 100644 --- a/tests/bugs/core_4118_test.py +++ b/tests/bugs/core_4118_test.py @@ -7,33 +7,42 @@ DESCRIPTION: JIRA: CORE-4118 FBTEST: bugs.core_4118 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """create table t (id int, d timestamp); -create index itd on t computed (cast(d as date)); -COMMIT; -""" +db = db_factory() -db = db_factory(init=init_script) +test_script = """ + create table t (id int, d timestamp); + create index itd on t computed (cast(d as date)); + commit; -test_script = """SET PLAN ON; -select * from t where cast(d as date) = current_date; -select * from (select id, cast(d as date) as d from t) where d = current_date; + SET PLAN ON; + select * from t where cast(d as date) = current_date; + select * from (select id, cast(d as date) as d from t) where d = current_date; """ act = isql_act('db', test_script) -expected_stdout = """ -PLAN (T INDEX (ITD)) -PLAN (T INDEX (ITD)) +expected_stdout_5x = """ + PLAN (T INDEX (ITD)) + PLAN (T INDEX (ITD)) +""" +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."ITD")) + PLAN ("PUBLIC"."T" INDEX ("PUBLIC"."ITD")) """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From bdac4ba6bc5e2e5f6a517b4f7c2308cf12a89e79 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 22:46:55 +0300 Subject: [PATCH 0810/1064] Added/Updated tests\bugs\core_4119_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4119_test.py | 44 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_4119_test.py b/tests/bugs/core_4119_test.py index 3a91c3c0..2ea6ed5f 100644 --- a/tests/bugs/core_4119_test.py +++ b/tests/bugs/core_4119_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4119 FBTEST: bugs.core_4119 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,28 +24,36 @@ act = python_act('db', substitutions=[('=.*', '')]) script_file = temp_file('test_script.sql') -expected_stdout = """ +expected_stdout_5x = """ + Procedure text: + begin + -- Моя процедура + end +""" + +expected_stdout_6x = """ + Procedure: PUBLIC.MYPROC Procedure text: - ============================================================================= begin -- Моя процедура end - ============================================================================= """ @pytest.mark.version('>=3.0') def test_1(act: Action, script_file: Path): - script_file.write_text(""" - set term ^; - create procedure myproc as - begin - -- Моя процедура - end^ - set term ;^ - show procedure myproc; - """, encoding='cp1251') - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input_file=script_file, charset='WIN1251') + sp_ddl = """ + set term ^; + create procedure myproc as + begin + -- Моя процедура + end^ + set term ;^ + show procedure myproc; + """ + + script_file.write_text(sp_ddl, encoding='cp1251') + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], input_file = script_file, charset='win1251') assert act.clean_stdout == act.clean_expected_stdout - From 962502b5c05b07679b350de4014a9a1b917243a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 28 Jun 2025 23:00:54 +0300 Subject: [PATCH 0811/1064] Added/Updated tests\bugs\core_4122_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4122_test.py | 78 ++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4122_test.py b/tests/bugs/core_4122_test.py index 5ac8819a..b7a82a10 100644 --- a/tests/bugs/core_4122_test.py +++ b/tests/bugs/core_4122_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4122 FBTEST: bugs.core_4122 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,7 +57,7 @@ act = python_act('db', substitutions=[('/* CREATE DATABASE .*', '')]) -expected_stdout = """ +expected_stdout_5x = """ SET SQL DIALECT 3; /* CREATE DATABASE 'localhost/3330:test.fdb' PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE; */ @@ -112,6 +118,7 @@ /* Package bodies */ /* Package body: PKG_TEST, Owner: SYSDBA */ + CREATE PACKAGE BODY PKG_TEST AS begin function F_TEST_INSIDE_PKG @@ -127,10 +134,75 @@ SET AUTODDL ON; """ +expected_stdout_6x = """ + SET SQL DIALECT 3; + /* + /* Schema definitions */ + /* Schema: PUBLIC, Owner: SYSDBA */ + CREATE OR ALTER SCHEMA PUBLIC; + COMMIT WORK; + COMMIT WORK; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Stored functions headers */ + CREATE OR ALTER FUNCTION PUBLIC.F_TEST_OUTSIDE_PKG RETURNS SMALLINT + AS + BEGIN END ^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Package headers */ + /* Package header: PUBLIC.PKG_TEST, Owner: SYSDBA */ + CREATE PACKAGE PUBLIC.PKG_TEST AS + begin + function F_TEST_INSIDE_PKG + returns smallint; + end^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Stored functions bodies */ + ALTER FUNCTION PUBLIC.F_TEST_OUTSIDE_PKG RETURNS SMALLINT + AS + begin + return -1; + end ^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + COMMIT WORK; + SET AUTODDL OFF; + SET TERM ^ ; + /* Package bodies */ + /* Package body: PUBLIC.PKG_TEST, Owner: SYSDBA */ + CREATE PACKAGE BODY PUBLIC.PKG_TEST AS + begin + function F_TEST_INSIDE_PKG + returns smallint + as + begin + return 1; + end + end^ + SET TERM ; ^ + COMMIT WORK; + SET AUTODDL ON; + /* Grant permissions for this database */ + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC; +""" + + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.isql(switches=['-x']) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-x'], combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 656d74f902243d284bd2b3906c041f1ce01052b1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 10:26:59 +0300 Subject: [PATCH 0812/1064] Updated tests\bugs\core_4137_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4137_test.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4137_test.py b/tests/bugs/core_4137_test.py index 52be3110..4e0a497a 100644 --- a/tests/bugs/core_4137_test.py +++ b/tests/bugs/core_4137_test.py @@ -69,14 +69,18 @@ expected_stdout_6x = """ SET SQL DIALECT 3; + /* Schema definitions */ + /* Schema: PUBLIC, Owner: SYSDBA */ + CREATE OR ALTER SCHEMA PUBLIC; + COMMIT WORK; /* Character sets */ - ALTER CHARACTER SET ISO8859_1 SET DEFAULT COLLATION PT_BR; + ALTER CHARACTER SET SYSTEM.ISO8859_1 SET DEFAULT COLLATION SYSTEM.PT_BR; COMMIT WORK; COMMIT WORK; SET AUTODDL OFF; SET TERM ^ ; /* Stored procedures headers */ - CREATE OR ALTER PROCEDURE TEST (P01 CHAR(10)) + CREATE OR ALTER PROCEDURE PUBLIC.TEST (P01 CHAR(10)) RETURNS (O01 VARCHAR(30)) AS BEGIN EXIT; END ^ @@ -87,7 +91,7 @@ SET AUTODDL OFF; SET TERM ^ ; /* Stored procedures bodies */ - ALTER PROCEDURE TEST (P01 CHAR(10)) + ALTER PROCEDURE PUBLIC.TEST (P01 CHAR(10)) RETURNS (O01 VARCHAR(30)) AS begin @@ -96,6 +100,8 @@ SET TERM ; ^ COMMIT WORK; SET AUTODDL ON; + /* Grant permissions for this database */ + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC; """ @pytest.mark.version('>=3.0') From c291756ee70984e638a40424785c63231de07267 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 10:30:24 +0300 Subject: [PATCH 0813/1064] Added/Updated tests\bugs\core_4149_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4149_test.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_4149_test.py b/tests/bugs/core_4149_test.py index 982b0d18..7f918af8 100644 --- a/tests/bugs/core_4149_test.py +++ b/tests/bugs/core_4149_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4149 FBTEST: bugs.core_4149 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,18 +37,29 @@ act = isql_act('db', test_script) -expected_stdout = """ -/* Grant permissions for this database */ -GRANT SELECT ON TEST TO PUBLIC +expected_stdout_5x = """ + /* Grant permissions for this database */ + GRANT SELECT ON TEST TO PUBLIC + + /* Grant permissions for this database */ + GRANT SELECT ON TEST TO PUBLIC + GRANT USAGE ON SEQUENCE G_TEST TO PUBLIC +""" + +expected_stdout_6x = """ + /* Grant permissions for this database */ + GRANT SELECT ON PUBLIC.TEST TO USER PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC -/* Grant permissions for this database */ -GRANT SELECT ON TEST TO PUBLIC -GRANT USAGE ON SEQUENCE G_TEST TO PUBLIC + /* Grant permissions for this database */ + GRANT SELECT ON PUBLIC.TEST TO USER PUBLIC + GRANT USAGE ON SEQUENCE PUBLIC.G_TEST TO USER PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From b58a9619b99be1c7ec67135fa36019fd1eb7423a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 10:33:45 +0300 Subject: [PATCH 0814/1064] Added/Updated tests\bugs\core_4156_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4156_test.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4156_test.py b/tests/bugs/core_4156_test.py index 7bdc5287..1218743d 100644 --- a/tests/bugs/core_4156_test.py +++ b/tests/bugs/core_4156_test.py @@ -12,6 +12,10 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,15 +36,18 @@ act = isql_act('db', test_script, substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[\t ]+', ' ')]) -expected_stdout = """ - 01: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 80 charset: 0 NONE - 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 80 charset: 0 NONE - 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 NONE - 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 -""" @pytest.mark.version('>=3.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 80 charset: 0 {SQL_SCHEMA_PREFIX}NONE + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 80 charset: 0 {SQL_SCHEMA_PREFIX}NONE + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 {SQL_SCHEMA_PREFIX}NONE + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From e693cd769fdad970bb60453bcb0d0f6d517a3340 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 10:43:36 +0300 Subject: [PATCH 0815/1064] Added/Updated tests\bugs\core_4160_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4160_test.py | 62 +++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_4160_test.py b/tests/bugs/core_4160_test.py index 3397af2e..aa1f6d5b 100644 --- a/tests/bugs/core_4160_test.py +++ b/tests/bugs/core_4160_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4160 FBTEST: bugs.core_4160 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,44 +55,78 @@ execute procedure sp_alert('jp', -6); """ -act = isql_act('db', test_script, substitutions=[('-At procedure.*', '')]) +substitutions = [ (r'line(:)?\s+\d+.*', '') ] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - Czech: New Balance bude menší než nula (-1) - + -At procedure 'SP_ALERT' Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - Portuguese: New saldo será menor do que zero (-2) - + -At procedure 'SP_ALERT' Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - Danish: New Balance vil være mindre end nul (-3) - + -At procedure 'SP_ALERT' Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - Greek: Νέα ισορροπία θα είναι κάτω από το μηδέν (-4) - + -At procedure 'SP_ALERT' Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - French: Nouveau solde sera inférieur à zéro (-5) - + -At procedure 'SP_ALERT' Statement failed, SQLSTATE = HY000 exception 1 -EX_NEGATIVE_REMAINDER - Russian: Новый остаток будет меньше нуля (-6) + -At procedure 'SP_ALERT' +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - Czech: New Balance bude menší než nula (-1) + -At procedure "PUBLIC"."SP_ALERT" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - Portuguese: New saldo será menor do que zero (-2) + -At procedure "PUBLIC"."SP_ALERT" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - Danish: New Balance vil være mindre end nul (-3) + -At procedure "PUBLIC"."SP_ALERT" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - Greek: Νέα ισορροπία θα είναι κάτω από το μηδέν (-4) + -At procedure "PUBLIC"."SP_ALERT" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - French: Nouveau solde sera inférieur à zéro (-5) + -At procedure "PUBLIC"."SP_ALERT" + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_NEGATIVE_REMAINDER" + - Russian: Новый остаток будет меньше нуля (-6) + -At procedure "PUBLIC"."SP_ALERT" """ @pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 141cd31f25a1b1e31f9b606c47c0a914615fbc37 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:07:33 +0300 Subject: [PATCH 0816/1064] Added/Updated tests\bugs\core_4165_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4165_test.py | 189 ++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 57 deletions(-) diff --git a/tests/bugs/core_4165_test.py b/tests/bugs/core_4165_test.py index d2422778..6e8a2ff3 100644 --- a/tests/bugs/core_4165_test.py +++ b/tests/bugs/core_4165_test.py @@ -7,8 +7,16 @@ DESCRIPTION: JIRA: CORE-4165 FBTEST: bugs.core_4165 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ +from firebird.driver import DatabaseError + import pytest from firebird.qa import * @@ -17,7 +25,7 @@ recreate table t2(id int); recreate table t3(id int); commit; - insert into t1 select rand()*100 from rdb$types,rdb$types; + insert into t1 select rand()*100 from rdb$types; commit; insert into t2 select * from t1; insert into t3 select * from t1; @@ -25,64 +33,131 @@ """ db = db_factory(init=init_script) +act = python_act('db', substitutions=[('record length.*', ''), ('key length.*', '')]) -test_script = """ - set planonly; - set explain on; - - select 0 i from t1 - union all - select 1 from t1 - union all - select 2 from t1 - ; - - - select 0 i from t2 - union - select 1 from t2 - union - select 2 from t2 - ; - - - select 0 i from t3 - union distinct - select 1 from t3 - union all - select 2 from t3 - ; - -- Note: values in 'record length' and 'key length' should be suppressed - -- because they contain not only size of field(s) but also db_key. -""" +#----------------------------------------------------------- -act = isql_act('db', test_script, substitutions=[('record length.*', ''), ('key length.*', '')]) - -expected_stdout = """ - Select Expression - -> Union - -> Table "T1" Full Scan - -> Table "T1" Full Scan - -> Table "T1" Full Scan - - Select Expression - -> Unique Sort (record length: 52, key length: 8) - -> Union - -> Table "T2" Full Scan - -> Table "T2" Full Scan - -> Table "T2" Full Scan - - Select Expression - -> Union - -> Unique Sort (record length: 44, key length: 8) - -> Union - -> Table "T3" Full Scan - -> Table "T3" Full Scan - -> Table "T3" Full Scan -""" +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- @pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() +def test_1(act: Action, capsys): + + qry_map = { + 1000 : + """ + select 0 i from t1 + union all + select 1 from t1 + union all + select 2 from t1 + """ + , + 2000 : + """ + select 0 i from t2 + union + select 1 from t2 + union + select 2 from t2 + """ + , + 3000 : + """ + select 0 i from t3 + union distinct + select 1 from t3 + union all + select 2 from t3 + """ + } + + with act.db.connect() as con: + cur = con.cursor() + + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) + + print(v) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + print('') + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + #rs = cur.execute(ps) + #for r in rs: + # print(r[0], r[1]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_stdout_5x = f""" + {qry_map[1000]} + Select Expression + ....-> Union + ........-> Table "T1" Full Scan + ........-> Table "T1" Full Scan + ........-> Table "T1" Full Scan + + {qry_map[2000]} + Select Expression + ....-> Unique Sort ( + ........-> Union + ............-> Table "T2" Full Scan + ............-> Table "T2" Full Scan + ............-> Table "T2" Full Scan + + {qry_map[3000]} + Select Expression + ....-> Union + ........-> Unique Sort ( + ............-> Union + ................-> Table "T3" Full Scan + ................-> Table "T3" Full Scan + ........-> Table "T3" Full Scan + """ + + expected_stdout_6x = f""" + {qry_map[1000]} + Select Expression + ....-> Union + ........-> Table "PUBLIC"."T1" Full Scan + ........-> Table "PUBLIC"."T1" Full Scan + ........-> Table "PUBLIC"."T1" Full Scan + + {qry_map[2000]} + Select Expression + ....-> Unique Sort ( + ........-> Union + ............-> Table "PUBLIC"."T2" Full Scan + ............-> Table "PUBLIC"."T2" Full Scan + ............-> Table "PUBLIC"."T2" Full Scan + + {qry_map[3000]} + Select Expression + ....-> Union + ........-> Unique Sort ( + ............-> Union + ................-> Table "PUBLIC"."T3" Full Scan + ................-> Table "PUBLIC"."T3" Full Scan + ........-> Table "PUBLIC"."T3" Full Scan + """ + + 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 From faddbe291ea26e7bc27b7e289bc5d851fd15795b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:19:22 +0300 Subject: [PATCH 0817/1064] Added/Updated tests\bugs\core_4203_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4203_test.py | 42 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_4203_test.py b/tests/bugs/core_4203_test.py index d306e668..2a73089d 100644 --- a/tests/bugs/core_4203_test.py +++ b/tests/bugs/core_4203_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4203 FBTEST: bugs.core_4203 +NOTES: + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,14 +20,14 @@ test_script = """ set term ^; - create package test1 as + create package pkg_test as begin function f1(x char(3)) returns char(6) ; end ^ commit ^ - create package body test1 as + create package body pkg_test as begin function f1(x char(3)) returns char(6) as begin @@ -32,30 +36,32 @@ end ^ - show package test1 + show package pkg_test ^ """ act = isql_act('db', test_script) -expected_stdout = """ - TEST1 - Header source: - begin - function f1(x char(3)) returns char(6) ; - end +@pytest.mark.version('>=3.0') +def test_1(act: Action): - Body source: - begin - function f1(x char(3)) returns char(6) as - begin - return x; + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + {SQL_SCHEMA_PREFIX}PKG_TEST + Header source: + begin + function f1(x char(3)) returns char(6) ; end - end -""" -@pytest.mark.version('>=3.0') -def test_1(act: Action): + Body source: + begin + function f1(x char(3)) returns char(6) as + begin + return x; + end + end + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 2cd912bbe297b2c187125b1d3b8d0db778971054 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:31:18 +0300 Subject: [PATCH 0818/1064] Added/Updated tests\bugs\core_4205_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4205_test.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4205_test.py b/tests/bugs/core_4205_test.py index 2cd39ecb..582b670a 100644 --- a/tests/bugs/core_4205_test.py +++ b/tests/bugs/core_4205_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4205 FBTEST: bugs.core_4205 +NOTES: + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -23,15 +27,17 @@ act = python_act('db', substitutions=[('^((?!(SQLSTATE|CREATE GENERATOR)).)*$', '')]) -expected_stdout = """ - CREATE GENERATOR TMP_GEN_42051 START WITH 9223372036854775807 INCREMENT -2147483647; - CREATE GENERATOR TMP_GEN_42052 START WITH -9223372036854775808 INCREMENT 2147483647; - CREATE GENERATOR TMP_GEN_42053 START WITH 9223372036854775807 INCREMENT 2147483647; - CREATE GENERATOR TMP_GEN_42054 START WITH -9223372036854775808 INCREMENT -2147483647; -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + CREATE GENERATOR {SQL_SCHEMA_PREFIX}TMP_GEN_42051 START WITH 9223372036854775807 INCREMENT -2147483647; + CREATE GENERATOR {SQL_SCHEMA_PREFIX}TMP_GEN_42052 START WITH -9223372036854775808 INCREMENT 2147483647; + CREATE GENERATOR {SQL_SCHEMA_PREFIX}TMP_GEN_42053 START WITH 9223372036854775807 INCREMENT 2147483647; + CREATE GENERATOR {SQL_SCHEMA_PREFIX}TMP_GEN_42054 START WITH -9223372036854775808 INCREMENT -2147483647; + """ + act.expected_stdout = expected_stdout act.isql(switches=['-x'], combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1a527f971b38a5cb61fcbfda8133dcbbbd80cde3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:33:11 +0300 Subject: [PATCH 0819/1064] Added/Updated tests\bugs\core_4210_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4210_test.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_4210_test.py b/tests/bugs/core_4210_test.py index 19b332ca..504248da 100644 --- a/tests/bugs/core_4210_test.py +++ b/tests/bugs/core_4210_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4210 FBTEST: bugs.core_4210 +NOTES: + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -76,24 +80,26 @@ act = isql_act('db', test_script) -expected_stdout = """ - Before altering proc: +@pytest.mark.version('>=3.0') +def test_1(act: Action): - COMMENT ON PROCEDURE PARAMETER SP_TEST.A_ID1 IS input id1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.A_DTS1 IS input timestamp1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.O_ID1 IS output id1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.O_DTS1 IS output timestamp1; + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + Before altering proc: - After altering proc: + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.A_ID1 IS input id1; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.A_DTS1 IS input timestamp1; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.O_ID1 IS output id1; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.O_DTS1 IS output timestamp1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.A_ID1 IS input id1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.A_DTS2 IS input timestamp2; - COMMENT ON PROCEDURE PARAMETER SP_TEST.O_ID1 IS output id1; - COMMENT ON PROCEDURE PARAMETER SP_TEST.O_DTS2 IS output timestamp2; -""" + After altering proc: + + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.A_ID1 IS input id1; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.A_DTS2 IS input timestamp2; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.O_ID1 IS output id1; + COMMENT ON PROCEDURE PARAMETER {SQL_SCHEMA_PREFIX}SP_TEST.O_DTS2 IS output timestamp2; + """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): act.expected_stdout = expected_stdout act.execute() assert act.clean_stdout == act.clean_expected_stdout From b4d576f900c05ca923e496d39f292809f989623b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:36:49 +0300 Subject: [PATCH 0820/1064] Added/Updated tests\bugs\core_4214_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4214_test.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_4214_test.py b/tests/bugs/core_4214_test.py index 86361b62..38405cbf 100644 --- a/tests/bugs/core_4214_test.py +++ b/tests/bugs/core_4214_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4214 FBTEST: bugs.core_4214 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,19 +37,32 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 unsuccessful metadata update -CREATE TABLE GTT_DETL failed -global temporary table "GTT_DETL" of type ON COMMIT DELETE ROWS cannot reference persistent table "FIX_MAIN" + Statement failed, SQLSTATE = HY000 unsuccessful metadata update -CREATE TABLE FIX_DETL failed -persistent table "FIX_DETL" cannot reference global temporary table "GTT_MAIN" of type ON COMMIT DELETE ROWS """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -CREATE TABLE "PUBLIC"."GTT_DETL" failed + -global temporary table "PUBLIC"."GTT_DETL" of type ON COMMIT DELETE ROWS cannot reference persistent table "PUBLIC"."FIX_MAIN" + + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -CREATE TABLE "PUBLIC"."FIX_DETL" failed + -persistent table "PUBLIC"."FIX_DETL" cannot reference global temporary table "PUBLIC"."GTT_MAIN" of type ON COMMIT DELETE ROWS +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f09b4101ec2fad9afc65ae2304eea863ccf15b2c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:48:34 +0300 Subject: [PATCH 0821/1064] Added/Updated tests\bugs\core_4244_test.py: Replaced 'SHOW' command with query to RDB tables. Bug still can be seen in 2.5.9.27156. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4244_test.py | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_4244_test.py b/tests/bugs/core_4244_test.py index 4b7e6861..91cde4fe 100644 --- a/tests/bugs/core_4244_test.py +++ b/tests/bugs/core_4244_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-4244 FBTEST: bugs.core_4244 +NOTES: + [29.06.2025] pzotov + Confirmed bug on 2.1.7.18553. + Replaced 'SHOW' command with query to RDB tables. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,9 +19,7 @@ db = db_factory() -test_script = """ - set term ^; - create or alter procedure sp_test as +PROC_DDL = """ declare char_one_byte char(1) character set dos864; declare str varchar(1000) character set dos864; begin @@ -24,31 +27,29 @@ str='B'; str=str||char_one_byte; end +""" +test_script = f""" + set list on; + set count on; + set term ^; + create or alter procedure sp_test as + {PROC_DDL} ^ set term ;^ commit; - -- Confirmed for 2.1.7: - -- Statement failed, SQLCODE = -802 - -- arithmetic exception, numeric overflow, or string truncation - -- -Cannot transliterate character between character sets - show proc sp_test; + select p.rdb$procedure_source as blob_id from rdb$procedures p where p.rdb$procedure_name = upper('sp_test'); """ -act = isql_act('db', test_script, substitutions=[('=.*', '')]) +substitutions = [('BLOB_ID.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - Procedure text: - declare char_one_byte char(1) character set dos864; - declare str varchar(1000) character set dos864; - begin - char_one_byte='A'; - str='B'; - str=str||char_one_byte; - end +expected_stdout = f""" + {PROC_DDL} + Records affected: 1 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From cf70132dd05d96fc3fce7b200895fb7c95290732 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 13:55:22 +0300 Subject: [PATCH 0822/1064] Added/Updated tests\bugs\core_4252_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4252_test.py | 42 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_4252_test.py b/tests/bugs/core_4252_test.py index 79392552..59a77cb3 100644 --- a/tests/bugs/core_4252_test.py +++ b/tests/bugs/core_4252_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4252 FBTEST: bugs.core_4252 +NOTES: + [28.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -34,32 +40,36 @@ db = db_factory(init=init_script) test_script = """ - show table t1; - show table "T2"; execute procedure sp_test(1); execute procedure sp_test(2); """ -act = isql_act('db', test_script, substitutions=[('line:.*', ''), ('col:.*', '')]) -expected_stdout = """ - X INTEGER Not Null - X INTEGER Not Null -""" +substitutions = [('line(:)?\\s+.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 validation error for column "T1"."X", value "*** null ***" - -At procedure 'SP_TEST' line: 3, col: 26 + -At procedure 'SP_TEST' + Statement failed, SQLSTATE = 23000 validation error for column "T2"."X", value "*** null ***" - -At procedure 'SP_TEST' line: 4, col: 8 + -At procedure 'SP_TEST' +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."T1"."X", value "*** null ***" + -At procedure "PUBLIC"."SP_TEST" + + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."T2"."X", value "*** null ***" + -At procedure "PUBLIC"."SP_TEST" """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1e1259da37ab9fb1fe27c76320af81685875810a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:03:14 +0300 Subject: [PATCH 0823/1064] Added/Updated tests\bugs\core_4262_test.py: Data in STDOUT has no matter. Only STDERR must be checked in this test. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4262_test.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4262_test.py b/tests/bugs/core_4262_test.py index 308a58b8..d9db0bd2 100644 --- a/tests/bugs/core_4262_test.py +++ b/tests/bugs/core_4262_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4262 FBTEST: bugs.core_4262 +NOTES: + [29.06.2025] pzotov + Data in STDOUT has no matter. + Only STDERR must be checked in this test. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,7 +20,19 @@ db = db_factory() -test_script = """set planonly; +test_script = """ +set list on; +select + case + when col = 1 then 'y' + when col = 0 then 'n' + end + as text +from ( + select case when exists (select 1 from rdb$database ) then 1 else 0 end as col + from rdb$relations +); + select col as col1, col as col2 from ( select case when exists (select 1 from rdb$database ) then 1 else 0 end as col @@ -24,13 +42,11 @@ act = isql_act('db', test_script) -expected_stdout = """ -PLAN (RDB$DATABASE NATURAL) -PLAN (RDB$RELATIONS NATURAL) +expected_stderr = """ """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout + act.expected_stderr = expected_stderr + act.execute(combine_output = False) # ::: NB ::: we have to check only EMPTY stderr here! + assert act.clean_stderr == act.clean_expected_stderr From 578825c37bfa3fc987515feb7a8495c69be7fc0d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:15:27 +0300 Subject: [PATCH 0824/1064] Added/Updated tests\bugs\core_4276_test.py: Removed 'SHOW' commands as having no sense in this test (it is enough to query just created table and check its data). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4276_test.py | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/bugs/core_4276_test.py b/tests/bugs/core_4276_test.py index 3a7386be..03270b2a 100644 --- a/tests/bugs/core_4276_test.py +++ b/tests/bugs/core_4276_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-4276 FBTEST: bugs.core_4276 +NOTES: + [29.06.2025] pzotov + Removed 'SHOW' commands as having no sense in this test (it is enough to query just created table and check its data). + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,56 +20,51 @@ db = db_factory() -act = python_act('db', substitutions=[('BLOB_CONTENT.*', '')]) +substitutions = [('[ \t]+', ' '), ('BLOB_ID.*', '')] +act = python_act('db', substitutions = substitutions) + +DATA_IN_VCHR = 'ÓßŌŃõÕµńĶķĻļņĒŅ' +DATA_IN_BLOB = """ + Green - viens no trim primārās krāsas, zaļā tiek uzskatīts diapazontsvetov spektrs ar viļņa + garumu aptuveni 500-565 nanometri. Sistēma CMYK druka zaļā iegūst, sajaucot dzelteno un + zilganzaļi (cyan).Dabā, Catalpa - zaļa augs. + Krāsu zaļie augi ir dabiski, ka cilvēks etalonomzeleni. + Zaļā koku varde. + Ir plaši izplatīti dabā. Lielākā daļa augu ir zaļā krāsā, jo tie satur pigmentu fotosintēzes - + hlorofilu (hlorofils absorbē lielu daļu no sarkano stariem saules spektra, atstājot uztveri + atstarotās un filtrē zaļā krāsā). Dzīvnieki ar zaļo krāsu tā izmantošanu maskēties fona augiem. +""" -test_script = """ +test_script = f""" recreate table "ĄČĘĢÆĖŠŚÖÜØ£"( "ąčęėįšųūž" varchar(50) character set dos775 ,"Õisu ja kariste järved" blob sub_type 1 character set dos775 ); commit; - show table; - show table "ĄČĘĢÆĖŠŚÖÜØ£"; + insert into "ĄČĘĢÆĖŠŚÖÜØ£"("ąčęėįšųūž", "Õisu ja kariste järved") values( - 'ÓßŌŃõÕµńĶķĻļņĒŅ', - 'Green - viens no trim primārās krāsas, zaļā tiek uzskatīts diapazontsvetov spektrs ar viļņa - garumu aptuveni 500-565 nanometri. Sistēma CMYK druka zaļā iegūst, sajaucot dzelteno un - zilganzaļi (cyan).Dabā, Catalpa - zaļa augs. - Krāsu zaļie augi ir dabiski, ka cilvēks etalonomzeleni. - Zaļā koku varde. - Ir plaši izplatīti dabā. Lielākā daļa augu ir zaļā krāsā, jo tie satur pigmentu fotosintēzes - - hlorofilu (hlorofils absorbē lielu daļu no sarkano stariem saules spektra, atstājot uztveri - atstarotās un filtrē zaļā krāsā). Dzīvnieki ar zaļo krāsu tā izmantošanu maskēties fona augiem.' + '{DATA_IN_VCHR}', + '{DATA_IN_BLOB}' ); set list on; set blob all; - select "ąčęėįšųūž", "Õisu ja kariste järved" as blob_content + select "ąčęėįšųūž", "Õisu ja kariste järved" as BLOB_ID from "ĄČĘĢÆĖŠŚÖÜØ£"; """ -expected_stdout = """ - ĄČĘĢÆĖŠŚÖÜØ£ - ąčęėįšųūž VARCHAR(50) CHARACTER SET DOS775 Nullable - Õisu ja kariste järved BLOB segment 80, subtype TEXT CHARACTER SET DOS775 Nullable - - ąčęėįšųūž ÓßŌŃõÕµńĶķĻļņĒŅ - BLOB_CONTENT 80:0 - Green - viens no trim primārās krāsas, zaļā tiek uzskatīts diapazontsvetov spektrs ar viļņa - garumu aptuveni 500-565 nanometri. Sistēma CMYK druka zaļā iegūst, sajaucot dzelteno un - zilganzaļi (cyan).Dabā, Catalpa - zaļa augs. - Krāsu zaļie augi ir dabiski, ka cilvēks etalonomzeleni. - Zaļā koku varde. - Ir plaši izplatīti dabā. Lielākā daļa augu ir zaļā krāsā, jo tie satur pigmentu fotosintēzes - - hlorofilu (hlorofils absorbē lielu daļu no sarkano stariem saules spektra, atstājot uztveri - atstarotās un filtrē zaļā krāsā). Dzīvnieki ar zaļo krāsu tā izmantošanu maskēties fona augiem. +expected_stdout = f""" + ąčęėįšųūž {DATA_IN_VCHR} + BLOB_ID 80:0 + {DATA_IN_BLOB} """ script_file = temp_file('test-script.sql') +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action, script_file: Path): script_file.write_text(test_script, encoding='cp775') act.expected_stdout = expected_stdout - act.isql(switches=['-q', '-b'], input_file=script_file, charset='DOS775') + act.isql(switches=['-q', '-b'], combine_output = True, input_file=script_file, charset='DOS775') assert act.clean_stdout == act.clean_expected_stdout From 4541c22d0a368c051bb5e1d7e51a2ed65957a9a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:17:51 +0300 Subject: [PATCH 0825/1064] Added/Updated tests\bugs\core_4280_test.py: Expected output on FB 6.x now has to include name of SQL schema. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4280_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4280_test.py b/tests/bugs/core_4280_test.py index 6a998565..206b16b8 100644 --- a/tests/bugs/core_4280_test.py +++ b/tests/bugs/core_4280_test.py @@ -10,6 +10,10 @@ NOTES: [30.09.2023] pzotov Expected error message become differ in FB 6.x, added splitting. + + [29.06.2025] pzotov + Expected output on FB 6.x now has to include name of SQL schema. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -40,10 +44,10 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 - CREATE FUNCTION PSQL_FUNC_TEST failed + CREATE FUNCTION "PUBLIC"."PSQL_FUNC_TEST" failed -Dynamic SQL Error -SQL error code = -637 - -duplicate specification of A_X - not supported + -duplicate specification of "A_X" - not supported """ @pytest.mark.version('>=3.0') From 4e65dc1e5dc20843ea720c9be0339a3e441849fd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:32:54 +0300 Subject: [PATCH 0826/1064] Added/Updated tests\bugs\core_4281_test.py: Removed 'SHOW' command. It is enought to check that function returns proper result after 'ALTE DOMAIN' statement. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4281_test.py | 39 +++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_4281_test.py b/tests/bugs/core_4281_test.py index c4d03b54..5bdc8c40 100644 --- a/tests/bugs/core_4281_test.py +++ b/tests/bugs/core_4281_test.py @@ -3,11 +3,14 @@ """ ID: issue-4604 ISSUE: 4604 -TITLE: FB 3: TYPE OF arguments of stored functions will hang firebird engine - if depending domain or column is changed +TITLE: FB 3: TYPE OF arguments of stored functions will hang firebird engine if depending domain or column is changed DESCRIPTION: JIRA: CORE-4281 FBTEST: bugs.core_4281 +NOTES: + [29.06.2025] pzotov + Removed 'SHOW' command. It is enought to check that function returns proper result after 'ALTE DOMAIN' statement. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,28 +19,40 @@ db = db_factory() test_script = """ - create domain testdomain as integer; - commit; + set list on; - create function testfunction (arg1 type of testdomain) returns integer as + create domain dm_test as integer; + commit; + set term ^; + create function fn_test (a_x type of dm_test) returns integer as begin - end; - + return sign(a_x); + end ^ + set term ;^ commit; - alter domain testdomain type bigint; + select fn_test(-2147483648) as fn_neg from rdb$database; + select fn_test( 2147483648) as fb_pos from rdb$database; + + alter domain dm_test type bigint; commit; - show domain testdomain; + select fn_test( 2147483648) as fb_pos from rdb$database; """ -act = isql_act('db', test_script) +substitutions = [('[\t ]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - TESTDOMAIN BIGINT Nullable + FN_NEG -1 + Statement failed, SQLSTATE = 22003 + arithmetic exception, numeric overflow, or string truncation + -numeric value is out of range + FB_POS 1 """ @pytest.mark.version('>=3.0') def test_1(act: Action): + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 225b16173e82dc9d78f19d5436121ba79cfe6e44 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:45:33 +0300 Subject: [PATCH 0827/1064] Added/Updated tests\bugs\core_4285_test.py: Re-implemented: use f-notation and dictionary with queries which SQL will be substituted in the expected output. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4285_test.py | 327 +++++++++++++++++++++-------------- 1 file changed, 197 insertions(+), 130 deletions(-) diff --git a/tests/bugs/core_4285_test.py b/tests/bugs/core_4285_test.py index b4316de9..9696e65a 100644 --- a/tests/bugs/core_4285_test.py +++ b/tests/bugs/core_4285_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-4285 FBTEST: bugs.core_4285 +NOTES: + [29.06.2025] pzotov + Re-implemented: use f-notation and dictionary with queries which SQL will be substituted in the expected output. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -39,139 +46,199 @@ """ db = db_factory(init=init_script) +act = python_act('db') -test_script = """ - set explain on; - set planonly; - set echo on; - - select 1 from test order by col1; - - ------ - select 1 from test where col1 = 0 order by col1; - - ------ - select 1 from test order by col1, col2; - - ------ - select 1 from test where col1 = 0 order by col1, col2; - - ------ - select 1 from test where col1 = 0 and col2 = 0 order by col1, col2; - - ------ - select 1 from test order by col1, col2, col3; - - ------ - select 1 from test where col1 = 0 order by col1, col2, col3; - - ------ - select 1 from test where col1 = 0 and col2 = 0 order by col1, col2, col3; - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1; - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1, col2, col3; - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1, col3; - -""" - -act = isql_act('db', test_script) - -expected_stdout = """ - select 1 from test order by col1; - - Select Expression - -> Table "TEST" Access By ID - -> Index "TEST_COL1" Full Scan - - ------ - select 1 from test where col1 = 0 order by col1; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL1" Range Scan (full match) +#----------------------------------------------------------- - ------ - select 1 from test order by col1, col2; +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped - Select Expression - -> Table "TEST" Access By ID - -> Index "TEST_COL12" Full Scan - - ------ - select 1 from test where col1 = 0 order by col1, col2; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL12" Range Scan (partial match: 1/2) - - ------ - select 1 from test where col1 = 0 and col2 = 0 order by col1, col2; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL12" Range Scan (full match) - - ------ - select 1 from test order by col1, col2, col3; - - Select Expression - -> Table "TEST" Access By ID - -> Index "TEST_COL123" Full Scan - - ------ - select 1 from test where col1 = 0 order by col1, col2, col3; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL123" Range Scan (partial match: 1/3) - - ------ - select 1 from test where col1 = 0 and col2 = 0 order by col1, col2, col3; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL123" Range Scan (partial match: 2/3) - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL132" Range Scan (partial match: 2/3) - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1, col2, col3; - - Select Expression - -> Sort (record length: 44, key length: 24) - -> Filter - -> Table "TEST" Access By ID - -> Bitmap - -> Index "TEST_COL132" Range Scan (partial match: 2/3) - - ------ - select 1 from test where col1 = 0 and col3 = 0 order by col1, col3; - - Select Expression - -> Filter - -> Table "TEST" Access By ID - -> Index "TEST_COL132" Range Scan (partial match: 2/3) - -""" +#----------------------------------------------------------- @pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() +def test_1(act: Action, capsys): + + qry_map = { + 1000 : 'select 1 from test order by col1' + ,1500 : 'select 1 from test where col1 = 0 order by col1' + ,2000 : 'select 1 from test order by col1, col2' + ,2500 : 'select 1 from test where col1 = 0 order by col1, col2' + ,3000 : 'select 1 from test where col1 = 0 and col2 = 0 order by col1, col2' + ,3500 : 'select 1 from test order by col1, col2, col3' + ,4000 : 'select 1 from test where col1 = 0 order by col1, col2, col3' + ,4500 : 'select 1 from test where col1 = 0 and col2 = 0 order by col1, col2, col3' + ,5000 : 'select 1 from test where col1 = 0 and col3 = 0 order by col1' + ,5500 : 'select 1 from test where col1 = 0 and col3 = 0 order by col1, col2, col3' + ,6000 : 'select 1 from test where col1 = 0 and col3 = 0 order by col1, col3' + } + + with act.db.connect() as con: + cur = con.cursor() + + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) + + print(v) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + print('') + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + #rs = cur.execute(ps) + #for r in rs: + # print(r[0], r[1]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_stdout_5x = f""" + + {qry_map[1000]} + Select Expression + ....-> Table "TEST" Access By ID + ........-> Index "TEST_COL1" Full Scan + + {qry_map[1500]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL1" Range Scan (full match) + + {qry_map[2000]} + Select Expression + ....-> Table "TEST" Access By ID + ........-> Index "TEST_COL12" Full Scan + + {qry_map[2500]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL12" Range Scan (partial match: 1/2) + + {qry_map[3000]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL12" Range Scan (full match) + + {qry_map[3500]} + Select Expression + ....-> Table "TEST" Access By ID + ........-> Index "TEST_COL123" Full Scan + + {qry_map[4000]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL123" Range Scan (partial match: 1/3) + + {qry_map[4500]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL123" Range Scan (partial match: 2/3) + + {qry_map[5000]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL132" Range Scan (partial match: 2/3) + + {qry_map[5500]} + Select Expression + ....-> Sort (record length: 44, key length: 24) + ........-> Filter + ............-> Table "TEST" Access By ID + ................-> Bitmap + ....................-> Index "TEST_COL132" Range Scan (partial match: 2/3) + + {qry_map[6000]} + Select Expression + ....-> Filter + ........-> Table "TEST" Access By ID + ............-> Index "TEST_COL132" Range Scan (partial match: 2/3) + """ + + expected_stdout_6x = f""" + {qry_map[1000]} + Select Expression + ....-> Table "PUBLIC"."TEST" Access By ID + ........-> Index "PUBLIC"."TEST_COL1" Full Scan + + {qry_map[1500]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL1" Range Scan (full match) + + {qry_map[2000]} + Select Expression + ....-> Table "PUBLIC"."TEST" Access By ID + ........-> Index "PUBLIC"."TEST_COL12" Full Scan + + {qry_map[2500]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL12" Range Scan (partial match: 1/2) + + {qry_map[3000]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL12" Range Scan (full match) + + {qry_map[3500]} + Select Expression + ....-> Table "PUBLIC"."TEST" Access By ID + ........-> Index "PUBLIC"."TEST_COL123" Full Scan + + {qry_map[4000]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL123" Range Scan (partial match: 1/3) + + {qry_map[4500]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL123" Range Scan (partial match: 2/3) + + {qry_map[5000]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL132" Range Scan (partial match: 2/3) + + {qry_map[5500]} + Select Expression + ....-> Sort (record length: 44, key length: 24) + ........-> Filter + ............-> Table "PUBLIC"."TEST" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_COL132" Range Scan (partial match: 2/3) + + {qry_map[6000]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Index "PUBLIC"."TEST_COL132" Range Scan (partial match: 2/3) + """ + + 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 From a5f466df9c4e26971c30346dc004589e8229abf9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 14:51:38 +0300 Subject: [PATCH 0828/1064] Added/Updated tests\bugs\core_4304_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4304_test.py | 71 ++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_4304_test.py b/tests/bugs/core_4304_test.py index 0edeb4cc..aeb628d7 100644 --- a/tests/bugs/core_4304_test.py +++ b/tests/bugs/core_4304_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4304 FBTEST: bugs.core_4304 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,36 +21,53 @@ db = db_factory() test_script = """ -recreate table t1(x int); -recreate table t1(x int, constraint t1_pk primary key(x), y int, constraint t1_fk foreign key(y) references t1(z)); -- NB: there is no field `z` in this table, this was misprit -recreate table t1(x int, constraint t1_pk primary key(x), y int, constraint t1_fk foreign key(y) references t1(x)); -commit; -show table t1; + set list on; + recreate table test(x int); + -- NB: there is no field `z` in this table: + recreate table test(x int, constraint test_pk primary key(x), y int, constraint test_fk foreign key(y) references test(z)); + recreate table test(x int, constraint test_pk primary key(x), y int, constraint test_fk foreign key(y) references test(x)); + commit; + insert into test(x, y) values(1, null); + insert into test(x, y) values(2, 1); + insert into test(x, y) values(3, 2); + update test set y = 3 where x = 1; + set count on; + select * from test order by x; """ -act = isql_act('db', test_script) +substitutions = [('[\t ]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ -X INTEGER Not Null -Y INTEGER Nullable -CONSTRAINT T1_FK: - Foreign key (Y) References T1 (X) -CONSTRAINT T1_PK: - Primary key (X) +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE TABLE TEST failed + -could not find UNIQUE or PRIMARY KEY constraint in table TEST with specified columns + X 1 + Y 3 + X 2 + Y 1 + X 3 + Y 2 + Records affected: 3 """ -expected_stderr = """ -Statement failed, SQLSTATE = 42000 -unsuccessful metadata update --RECREATE TABLE T1 failed --could not find UNIQUE or PRIMARY KEY constraint in table T1 with specified columns +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE TABLE "PUBLIC"."TEST" failed + -could not find UNIQUE or PRIMARY KEY constraint in table "PUBLIC"."TEST" with specified columns + X 1 + Y 3 + X 2 + Y 1 + X 3 + Y 2 + Records affected: 3 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3eff925852f557f56ab690287babb6a94280fd73 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 15:04:48 +0300 Subject: [PATCH 0829/1064] Added/Updated tests\bugs\core_4315_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4315_test.py | 191 ++++++++++++++++++++++++++++++++--- 1 file changed, 178 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_4315_test.py b/tests/bugs/core_4315_test.py index be90895f..adbc3424 100644 --- a/tests/bugs/core_4315_test.py +++ b/tests/bugs/core_4315_test.py @@ -3,25 +3,27 @@ """ ID: issue-4638 ISSUE: 4638 -TITLE: Usage of field(s) alias in view WITH CHECK OPTION leads to incorrect compile - error or incorrect internal triggers +TITLE: Usage of field(s) alias in view WITH CHECK OPTION leads to incorrect compile error or incorrect internal triggers DESCRIPTION: JIRA: CORE-4315 FBTEST: bugs.core_4315 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ recreate view v1 as select 1 id from rdb$database; commit; recreate table t1 (n1 integer, n2 integer); -""" - -db = db_factory(init=init_script) - -test_script = """ -- Compilation error in LI-T3.0.0.30830 (13-jan-2014): "Column unknown": recreate view v1 as select t1.n1 from t1 t1 where t1.n1 < t1.n2 with check option; recreate view v1 as select t1.n1 from t1 where t1.n1 < t1.n2 with check option; @@ -39,9 +41,10 @@ order by rdb$trigger_name; """ -act = isql_act('db', test_script, substitutions=[('RDB\\$TRIGGER_BLR.*', '')]) +substitutions = [('[\t ]+', ' '), ('RDB\\$TRIGGER_BLR.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ RDB$TRIGGER_BLR c:2d2 blr_version5, blr_begin, @@ -82,9 +85,171 @@ blr_eoc """ +expected_stdout_6x = """ +RDB$TRIGGER_BLR c:1e0 + blr_version5, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation2, 2, 'T','1', + 4, 34,'T','1',34, 2, + blr_boolean, + blr_and, + blr_lss, + blr_field, 2, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_equiv, + blr_field, 0, 2, 'N','1', + blr_field, 2, 2, 'N','1', + blr_end, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e1 + blr_version5, + blr_begin, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_null, + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e2 + blr_version5, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 2, 'T','1', 2, + blr_boolean, + blr_and, + blr_lss, + blr_field, 2, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_equiv, + blr_field, 0, 2, 'N','1', + blr_field, 2, 2, 'N','1', + blr_end, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e3 + blr_version5, + blr_begin, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_null, + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e4 + blr_version5, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation2, 2, 'T','1', + 3, 34,'X',34, 2, + blr_boolean, + blr_and, + blr_lss, + blr_field, 2, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_equiv, + blr_field, 0, 2, 'N','1', + blr_field, 2, 2, 'N','1', + blr_end, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e5 + blr_version5, + blr_begin, + blr_if, + blr_lss, + blr_field, 1, 2, 'N','1', + blr_null, + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e6 + blr_version5, + blr_begin, + blr_for, + blr_rse, 1, + blr_relation, 2, 'T','1', 2, + blr_boolean, + blr_and, + blr_lss, + blr_field, 2, 2, 'N','1', + blr_field, 2, 2, 'N','2', + blr_equiv, + blr_field, 0, 1, 'A', + blr_field, 2, 2, 'N','1', + blr_end, + blr_if, + blr_lss, + blr_field, 1, 1, 'A', + blr_field, 2, 2, 'N','2', + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc + + +RDB$TRIGGER_BLR c:1e7 + blr_version5, + blr_begin, + blr_if, + blr_lss, + blr_field, 1, 1, 'A', + blr_null, + blr_begin, + blr_end, + blr_abort, blr_gds_code, 16, 'c','h','e','c','k','_','c','o','n','s','t','r','a','i','n','t', + blr_end, + blr_eoc +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 08138a4502788477ae58dc2f0228cf903df9f9d5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 15:29:57 +0300 Subject: [PATCH 0830/1064] Added/Updated tests\bugs\core_4318_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4318_test.py | 159 +++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 55 deletions(-) diff --git a/tests/bugs/core_4318_test.py b/tests/bugs/core_4318_test.py index bac53dce..91686332 100644 --- a/tests/bugs/core_4318_test.py +++ b/tests/bugs/core_4318_test.py @@ -7,7 +7,23 @@ DESCRIPTION: JIRA: CORE-4318 FBTEST: bugs.core_4318 +NOTES: + [29.06.2025] pzotov + 1. In 3.0.0.30837 plan was: + Select Expression + -> Singularity Check + -> Filter + -> Aggregate + -> Table "T T2" Access By ID + -> Index "FK_T2_REF_T1" Scan + (i.e. there was NO "Filter" between "Aggregate" and "Table "T T2" Access By ID") + 2. Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + """ +from firebird.driver import DatabaseError import pytest from firebird.qa import * @@ -55,64 +71,97 @@ db = db_factory(init=init_script) -test_script = """ - set explain on; - set planonly; +# line 5, column 15 ==> line N, column N +substitutions = [ ( r'line(:)?\s+\d+', 'line N' ), ( r'col(umn)?(:)?\s+\d+', 'column N' ) ] +act = python_act('db', substitutions = substitutions) - set term ^; - execute block returns (s integer) as - declare v integer = 1; - begin - with t as ( - select t1_id as t1_id, sum(id) as s -- FB 5.x: "Select Expression (line NNN, column MMM)" - from t2 - group by 1 - ) - select s - from t - where t1_id = :v - into :s; - - suspend; - end - ^ - set term ;^ - -- In 3.0.0.30837 plan was: - -- Select Expression - -- -> Singularity Check - -- -> Filter - -- -> Aggregate - -- -> Table "T T2" Access By ID - -- -> Index "FK_T2_REF_T1" Scan - -- (i.e. there was NO "Filter" between "Aggregate" and "Table "T T2" Access By ID") -""" +#----------------------------------------------------------- -act = isql_act('db', test_script, substitutions = [('line \\d+, col(umn)? \\d+', 'line, col')]) +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped -fb3x_expected_out = """ - Select Expression - -> Singularity Check - -> Filter - -> Aggregate - -> Filter - -> Table "T2" as "T T2" Access By ID - -> Index "FK_T2_REF_T1" Range Scan (full match) -""" - -fb5x_expected_out = """ - Select Expression (line 8, column 7) - -> Singularity Check - -> Filter - -> Aggregate - -> Filter - -> Table "T2" as "T T2" Access By ID - -> Index "FK_T2_REF_T1" Range Scan (full match) -""" +#----------------------------------------------------------- @pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = fb3x_expected_out if act.is_version('<5') else fb5x_expected_out - act.execute() - #assert act.stdout == act.clean_expected_stdout +def test_1(act: Action, capsys): + + qry_map = { + 1000 : + """ + execute block returns (s integer) as + declare v integer = 1; + begin + with t as ( + select t1_id as t1_id, sum(id) as s -- FB 5.x: "Select Expression (line NNN, column MMM)" + from t2 + group by 1 + ) + select s + from t + where t1_id = :v + into :s; + + suspend; + end + + """ + } + + with act.db.connect() as con: + cur = con.cursor() + + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) + + print(v) + # Print explained plan with padding eash line by dots in order to see indentations: + 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 rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() # <<< 29.06.2025 NEED EVEN IF CURSOR WAS NOT SELECT ANY DATA! OTHERWISE PYTEST CAN HANG ON EXIT! + + expected_stdout_4x = f""" + {qry_map[1000]} + Select Expression + ....-> Singularity Check + ........-> Filter + ............-> Aggregate + ................-> Filter + ....................-> Table "T2" as "T T2" Access By ID + ........................-> Index "FK_T2_REF_T1" Range Scan (full match) + """ + + expected_stdout_5x = f""" + {qry_map[1000]} + Select Expression (line N, column N) + ....-> Singularity Check + ........-> Filter + ............-> Aggregate + ................-> Filter + ....................-> Table "T2" as "T T2" Access By ID + ........................-> Index "FK_T2_REF_T1" Range Scan (full match) + """ + + expected_stdout_6x = f""" + {qry_map[1000]} + Select Expression (line N, column N) + ....-> Singularity Check + ........-> Filter + ............-> Aggregate + ................-> Filter + ....................-> Table "PUBLIC"."T2" as "T" "PUBLIC"."T2" Access By ID + ........................-> Index "PUBLIC"."FK_T2_REF_T1" Range Scan (full match) + """ + + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else 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 - From 00531426466eb6d82b2b1cd8ff476cd4b192a2d2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 15:51:37 +0300 Subject: [PATCH 0831/1064] Added/Updated tests\bugs\core_4342_test.py: Re-implemented: use f-notation to substitute fixture values in the expected output. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4342_test.py | 202 ++++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 84 deletions(-) diff --git a/tests/bugs/core_4342_test.py b/tests/bugs/core_4342_test.py index 97096578..ad809449 100644 --- a/tests/bugs/core_4342_test.py +++ b/tests/bugs/core_4342_test.py @@ -7,101 +7,135 @@ DESCRIPTION: JIRA: CORE-4342 FBTEST: bugs.core_4342 +NOTES: + [29.06.2025] pzotov + Re-implemented: use f-notation to substitute fixture values in the expected output. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * db = db_factory() -user_boss = user_factory('db', name='boss', password='123') -user_mngr = user_factory('db', name='mngr', password='456') - -test_script = """ - -- Add these DDL privileges in order to have some rows in - -- rdb$security_classes table for user BOSS: - grant create table to boss; - grant alter any table to boss; - grant drop any table to boss; - commit; - - set list on; - select current_user,count(*) acl_count from rdb$security_classes where rdb$acl containing 'boss'; - - select 1 from rdb$security_classes where rdb$acl containing 'boss' with lock; - update rdb$security_classes set rdb$security_class = rdb$security_class where rdb$acl containing 'boss'; - delete from rdb$security_classes where rdb$acl containing 'boss'; - commit; - - connect '$(DSN)' user 'MNGR' password '456'; - select current_user,count(*) acl_count from rdb$security_classes where rdb$acl containing 'boss'; - - select 1 from rdb$security_classes where rdb$acl containing 'boss' with lock; - update rdb$security_classes set rdb$security_class = rdb$security_class where rdb$acl containing 'boss'; - delete from rdb$security_classes where rdb$acl containing 'boss'; - commit; -""" +tmp_boss = user_factory('db', name='boss', password='123') +tmp_mngr = user_factory('db', name='mngr', password='456') -expected_stdout = """ - USER SYSDBA - ACL_COUNT 1 +substitutions = [('[\t ]+', ' ')] +act = isql_act('db', substitutions = substitutions) - USER MNGR - ACL_COUNT 1 -""" +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_boss: User, tmp_mngr: User): -# version: 3.0 - -act = isql_act('db', test_script) - -expected_stderr_1 = """ - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK - Statement failed, SQLSTATE = 42000 - UPDATE operation is not allowed for system table RDB$SECURITY_CLASSES - Statement failed, SQLSTATE = 42000 - DELETE operation is not allowed for system table RDB$SECURITY_CLASSES - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$SECURITY_CLASSES - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$SECURITY_CLASSES -""" + test_script = f""" + -- Add these DDL privileges in order to have some rows in + -- rdb$security_classes table for user {tmp_boss.name}: + grant create table to {tmp_boss.name}; + grant alter any table to {tmp_boss.name}; + grant drop any table to {tmp_boss.name}; + commit; + set list on; + select current_user,count(*) acl_count from rdb$security_classes where rdb$acl containing '{tmp_boss.name}'; -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action, user_boss: User, user_mngr: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - -# version: 4.0 - -expected_stderr_2 = """ - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK - Statement failed, SQLSTATE = 42000 - UPDATE operation is not allowed for system table RDB$SECURITY_CLASSES - Statement failed, SQLSTATE = 42000 - DELETE operation is not allowed for system table RDB$SECURITY_CLASSES - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$SECURITY_CLASSES - -Effective user is MNGR - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$SECURITY_CLASSES - -Effective user is MNGR -""" + select 1 from rdb$security_classes where rdb$acl containing '{tmp_boss.name}' with lock; + update rdb$security_classes set rdb$security_class = rdb$security_class where rdb$acl containing '{tmp_boss.name}'; + delete from rdb$security_classes where rdb$acl containing '{tmp_boss.name}'; + commit; + + connect '{act.db.dsn}' user '{tmp_mngr.name}' password '{tmp_mngr.password}'; + select current_user,count(*) acl_count from rdb$security_classes where rdb$acl containing '{tmp_boss.name}'; + + select 1 from rdb$security_classes where rdb$acl containing '{tmp_boss.name}' with lock; + update rdb$security_classes set rdb$security_class = rdb$security_class where rdb$acl containing '{tmp_boss.name}'; + delete from rdb$security_classes where rdb$acl containing '{tmp_boss.name}'; + commit; + """ + + expected_stdout_3x = f""" + USER {act.db.user.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK + + Statement failed, SQLSTATE = 42000 + UPDATE operation is not allowed for system table RDB$SECURITY_CLASSES + + Statement failed, SQLSTATE = 42000 + DELETE operation is not allowed for system table RDB$SECURITY_CLASSES + + USER {tmp_mngr.name.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$SECURITY_CLASSES + + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$SECURITY_CLASSES + """ + + expected_stdout_5x = f""" + USER {act.db.user.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK + + Statement failed, SQLSTATE = 42000 + UPDATE operation is not allowed for system table RDB$SECURITY_CLASSES + + Statement failed, SQLSTATE = 42000 + DELETE operation is not allowed for system table RDB$SECURITY_CLASSES + + USER {tmp_mngr.name.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$SECURITY_CLASSES for update WITH LOCK + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$SECURITY_CLASSES + -Effective user is {tmp_mngr.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$SECURITY_CLASSES + -Effective user is {tmp_mngr.name.upper()} + """ + + + expected_stdout_6x = f""" + USER {act.db.user.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table "SYSTEM"."RDB$SECURITY_CLASSES" for update WITH LOCK + + Statement failed, SQLSTATE = 42000 + UPDATE operation is not allowed for system table "SYSTEM"."RDB$SECURITY_CLASSES" + Statement failed, SQLSTATE = 42000 + + DELETE operation is not allowed for system table "SYSTEM"."RDB$SECURITY_CLASSES" + USER {tmp_mngr.name.upper()} + ACL_COUNT 1 + + Statement failed, SQLSTATE = HY000 + Cannot select system table "SYSTEM"."RDB$SECURITY_CLASSES" for update WITH LOCK + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE "SYSTEM"."RDB$SECURITY_CLASSES" + -Effective user is {tmp_mngr.name.upper()} -@pytest.mark.version('>=4.0') -def test_2(act: Action, user_boss: User, user_mngr: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE "SYSTEM"."RDB$SECURITY_CLASSES" + -Effective user is {tmp_mngr.name.upper()} + """ + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 17480677d7c8e617c4ef8238ade089dc1e682cf8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 15:57:33 +0300 Subject: [PATCH 0832/1064] Added/Updated tests\bugs\core_4350_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4350_test.py | 86 +++++++++++++++++------------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/tests/bugs/core_4350_test.py b/tests/bugs/core_4350_test.py index 7fb76177..d341922d 100644 --- a/tests/bugs/core_4350_test.py +++ b/tests/bugs/core_4350_test.py @@ -5,17 +5,20 @@ ISSUE: 4672 TITLE: Support the SQL Standard ALTER SEQUENCE .. RESTART (without WITH clause) DESCRIPTION: -NOTES: -[18.08.2020] - FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): - statement 'alter sequence restart with 0' changes rdb$generators.rdb$initial_value to -1 thus next call - gen_id(,1) will return 0 (ZERO!) rather than 1. - See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d - This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt - - Because of this, it was decided to make separate section for check results of FB 4.x JIRA: CORE-4350 FBTEST: bugs.core_4350 +NOTES: + [18.08.2020] + FB 4.x has incompatible behaviour with all previous versions since build 4.0.0.2131 (06-aug-2020): + statement 'alter sequence restart with 0' changes rdb$generators.rdb$initial_value to -1 thus next call + gen_id(,1) will return 0 (ZERO!) rather than 1. + See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d + This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt + Because of this, it was decided to make separate section for check results of FB 4.x + + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -44,42 +47,35 @@ act = isql_act('db', test_script, substitutions=[('=.*', ''), ('[ \t]+', ' ')]) -# version: 3.0 - -expected_stdout_1 = """ - NEXT_VALUE 9223372034707292160 - NEXT_VALUE -9223372034707292161 - NEXT_VALUE -9223372034707292162 - NEXT_VALUE 9223372034707292161 - - Generator G1, current value: 9223372036854775807, initial value: 9223372036854775807, increment: -2147483647 - Generator G2, current value: -9223372036854775808, initial value: -9223372036854775808, increment: 2147483647 - Generator G3, current value: 9223372036854775807, initial value: 9223372036854775807, increment: 2147483647 - Generator G4, current value: -9223372036854775808, initial value: -9223372036854775808, increment: -2147483647 -""" - -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout_1 - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - -# version: 4.0 - -expected_stdout_2 = """ - NEXT_VALUE 9223372036854775807 - NEXT_VALUE -9223372036854775808 - NEXT_VALUE 9223372036854775807 - NEXT_VALUE -9223372036854775808 - Generator G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647 - Generator G2, current value: 9223372034707292161, initial value: -9223372036854775808, increment: 2147483647 - Generator G3, current value: 9223372034707292160, initial value: 9223372036854775807, increment: 2147483647 - Generator G4, current value: -9223372034707292161, initial value: -9223372036854775808, increment: -2147483647 -""" - -@pytest.mark.version('>=4.0') +@pytest.mark.version('>=3.0') def test_2(act: Action): - act.expected_stdout = expected_stdout_2 - act.execute() + + expected_stdout_3x = """ + NEXT_VALUE 9223372034707292160 + NEXT_VALUE -9223372034707292161 + NEXT_VALUE -9223372034707292162 + NEXT_VALUE 9223372034707292161 + + Generator G1, current value: 9223372036854775807, initial value: 9223372036854775807, increment: -2147483647 + Generator G2, current value: -9223372036854775808, initial value: -9223372036854775808, increment: 2147483647 + Generator G3, current value: 9223372036854775807, initial value: 9223372036854775807, increment: 2147483647 + Generator G4, current value: -9223372036854775808, initial value: -9223372036854775808, increment: -2147483647 + """ + + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout_4x = f""" + NEXT_VALUE 9223372036854775807 + NEXT_VALUE -9223372036854775808 + NEXT_VALUE 9223372036854775807 + NEXT_VALUE -9223372036854775808 + Generator {SQL_SCHEMA_PREFIX}G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647 + Generator {SQL_SCHEMA_PREFIX}G2, current value: 9223372034707292161, initial value: -9223372036854775808, increment: 2147483647 + Generator {SQL_SCHEMA_PREFIX}G3, current value: 9223372034707292160, initial value: 9223372036854775807, increment: 2147483647 + Generator {SQL_SCHEMA_PREFIX}G4, current value: -9223372034707292161, initial value: -9223372036854775808, increment: -2147483647 + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_4x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ace6350b4228fa57cab145a323672f5d0333ae2c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:07:59 +0300 Subject: [PATCH 0833/1064] Added/Updated tests\bugs\core_4359_test.py: Re-implemented: use f-notation to substitute fixture values in the expected output. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4359_test.py | 163 ++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 70 deletions(-) diff --git a/tests/bugs/core_4359_test.py b/tests/bugs/core_4359_test.py index 55de67b7..d93037fd 100644 --- a/tests/bugs/core_4359_test.py +++ b/tests/bugs/core_4359_test.py @@ -7,105 +7,128 @@ DESCRIPTION: JIRA: CORE-4359 FBTEST: bugs.core_4359 +NOTES: + [29.06.2025] pzotov + Re-implemented: use f-notation to substitute fixture values in the expected output. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * db = db_factory() -user_boss = user_factory('db', name='boss', password='123') +tmp_user = user_factory('db', name='boss', password='123') -test_script = """ - -- Test scenario attempts to modify (or lock record) from RDB$DATABASE - -- both for SYSDBA and non-privileged user. - set count on; +act = isql_act('db') - insert into rdb$database(rdb$security_class) values(''); - delete from rdb$database where rdb$security_class = ''; - update rdb$database set rdb$security_class = rdb$security_class where rdb$security_class = ''; - select current_user from rdb$database with lock; +@pytest.mark.version('>=3.0') +def test_1(act: Action, tmp_user: User): - commit; + test_script = f""" + -- Test scenario attempts to modify (or lock record) from RDB$DATABASE + -- both for SYSDBA and non-privileged user. + set count on; - connect '$(DSN)' user boss password '123'; + insert into rdb$database(rdb$security_class) values(''); + delete from rdb$database where rdb$security_class = ''; + update rdb$database set rdb$security_class = rdb$security_class where rdb$security_class = ''; + select current_user from rdb$database with lock; - insert into rdb$database(rdb$security_class) values(''); - delete from rdb$database where rdb$security_class = ''; - update rdb$database set rdb$security_class = rdb$security_class where rdb$security_class = ''; - select current_user from rdb$database with lock; + commit; - commit; -""" + connect '{act.db.dsn}' user {tmp_user.name} password '{tmp_user.password}'; -act = isql_act('db', test_script) + insert into rdb$database(rdb$security_class) values(''); + delete from rdb$database where rdb$security_class = ''; + update rdb$database set rdb$security_class = rdb$security_class where rdb$security_class = ''; + select current_user from rdb$database with lock; -expected_stdout = """ - Records affected: 0 - Records affected: 0 - Records affected: 0 -""" + commit; + """ -# version: 3.0 -expected_stderr_1 = """ - Statement failed, SQLSTATE = 42000 - INSERT operation is not allowed for system table RDB$DATABASE + expected_stdout_3x = """ + Statement failed, SQLSTATE = 42000 + INSERT operation is not allowed for system table RDB$DATABASE - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$DATABASE for update WITH LOCK + Records affected: 0 + Records affected: 0 + Records affected: 0 - Statement failed, SQLSTATE = 28000 - no permission for INSERT access to TABLE RDB$DATABASE + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$DATABASE + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$DATABASE - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$DATABASE + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$DATABASE - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$DATABASE for update WITH LOCK -""" + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action, user_boss: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK + """ -# version: 4.0 + expected_stdout_4x = f""" + Statement failed, SQLSTATE = 42000 + INSERT operation is not allowed for system table RDB$DATABASE -expected_stderr_2 = """ - Statement failed, SQLSTATE = 42000 - INSERT operation is not allowed for system table RDB$DATABASE + Records affected: 0 + Records affected: 0 + Records affected: 0 - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$DATABASE for update WITH LOCK + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK - Statement failed, SQLSTATE = 28000 - no permission for INSERT access to TABLE RDB$DATABASE - -Effective user is BOSS + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} - Statement failed, SQLSTATE = 28000 - no permission for DELETE access to TABLE RDB$DATABASE - -Effective user is BOSS + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to TABLE RDB$DATABASE - -Effective user is BOSS + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE RDB$DATABASE + -Effective user is {tmp_user.name.upper()} - Statement failed, SQLSTATE = HY000 - Cannot select system table RDB$DATABASE for update WITH LOCK -""" + Statement failed, SQLSTATE = HY000 + Cannot select system table RDB$DATABASE for update WITH LOCK + """ + + expected_stdout_6x = f""" + Statement failed, SQLSTATE = 42000 + INSERT operation is not allowed for system table "SYSTEM"."RDB$DATABASE" + + Records affected: 0 + Records affected: 0 + Records affected: 0 + + Statement failed, SQLSTATE = HY000 + Cannot select system table "SYSTEM"."RDB$DATABASE" for update WITH LOCK + + Statement failed, SQLSTATE = 28000 + no permission for INSERT access to TABLE "SYSTEM"."RDB$DATABASE" + -Effective user is {tmp_user.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for DELETE access to TABLE "SYSTEM"."RDB$DATABASE" + + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to TABLE "SYSTEM"."RDB$DATABASE" + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = HY000 + Cannot select system table "SYSTEM"."RDB$DATABASE" for update WITH LOCK + """ -@pytest.mark.version('>=4.0') -def test_2(act: Action, user_boss: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_4x if act.is_version('<6') else expected_stdout_6x + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3b7f589b6d7bc48a5160bfa5e5d672b26b28474d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:42:29 +0300 Subject: [PATCH 0834/1064] Added/Updated tests\bugs\core_4365_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4365_test.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4365_test.py b/tests/bugs/core_4365_test.py index aafa2ef9..51028e79 100644 --- a/tests/bugs/core_4365_test.py +++ b/tests/bugs/core_4365_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4365 FBTEST: bugs.core_4365 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -30,15 +36,18 @@ where id = 1; """ -act = isql_act('db', test_script, substitutions=[('RDB\\$INDEX_[0-9]+', 'RDB\\$INDEX')]) +act = isql_act('db', test_script, substitutions=[('RDB\\$INDEX_[0-9]+', 'RDB$INDEX_*')]) + +expected_stdout_5x = """ + PLAN JOIN (JOIN (X RF G1 INDEX (RDB$INDEX_*), X RF G2 INDEX (RDB$INDEX_*), X R INDEX (RDB$INDEX_*)), X P INDEX (RDB$INDEX_*)) +""" -expected_stdout = """ - PLAN JOIN (JOIN (X RF G1 INDEX (RDB$INDEX_46), X RF G2 INDEX (RDB$INDEX_46), X R INDEX (RDB$INDEX_1)), X P INDEX (RDB$INDEX_22)) +expected_stdout_6x = """ + PLAN JOIN (JOIN ("X" "RF" "G1" INDEX ("SYSTEM"."RDB$INDEX_*"), "X" "RF" "G2" INDEX ("SYSTEM"."RDB$INDEX_*"), "X" "R" INDEX ("SYSTEM"."RDB$INDEX_*")), "X" "P" INDEX ("SYSTEM"."RDB$INDEX_*")) """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From f82c95465c3880cc27e4e6b2939d68a69a50beab Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:45:23 +0300 Subject: [PATCH 0835/1064] Added/Updated tests\bugs\core_4371_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4371_test.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_4371_test.py b/tests/bugs/core_4371_test.py index f4d5beaa..616c6a9f 100644 --- a/tests/bugs/core_4371_test.py +++ b/tests/bugs/core_4371_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4371 FBTEST: bugs.core_4371 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -30,18 +36,25 @@ set term ;^ """ -act = isql_act('db', test_script) +substitutions = [('at offset \\d+', 'at offset')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + Statement failed, SQLSTATE = 2F000 + Error while parsing function FN_TEST's BLR + -invalid request BLR at offset + -exception EX_SOME_NON_EXISTENT_NAME not defined +""" -expected_stderr = """ -Statement failed, SQLSTATE = 2F000 -Error while parsing function FN_TEST's BLR --invalid request BLR at offset 55 --exception EX_SOME_NON_EXISTENT_NAME not defined +expected_stdout_6x = """ + Statement failed, SQLSTATE = 2F000 + Error while parsing function "PUBLIC"."FN_TEST"'s BLR + -invalid request BLR at offset + -exception "PUBLIC"."EX_SOME_NON_EXISTENT_NAME" not defined """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From bc1f3ca6d98a40c592679e6f907c3c59fd02a102 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:47:45 +0300 Subject: [PATCH 0836/1064] Added/Updated tests\bugs\core_4373_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4373_test.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_4373_test.py b/tests/bugs/core_4373_test.py index dfdb120a..6e96a02f 100644 --- a/tests/bugs/core_4373_test.py +++ b/tests/bugs/core_4373_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4373 FBTEST: bugs.core_4373 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,7 +55,7 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 CREATE PACKAGE NEW_PACKAGE failed -Duplicate PROCEDURE EXTERNAL_PROC @@ -59,9 +65,18 @@ -Duplicate PROCEDURE INTERNAL_PROC """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + CREATE PACKAGE "PUBLIC"."NEW_PACKAGE" failed + -Duplicate PROCEDURE "EXTERNAL_PROC" + + Statement failed, SQLSTATE = 42000 + CREATE PACKAGE BODY "PUBLIC"."NEW_PACKAGE" failed + -Duplicate PROCEDURE "INTERNAL_PROC" +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a23d112629adc27b282c7af5017061c61c3e5e88 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:51:34 +0300 Subject: [PATCH 0837/1064] Added/Updated tests\bugs\core_4376_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4376_test.py | 39 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_4376_test.py b/tests/bugs/core_4376_test.py index 22705f3a..c1252732 100644 --- a/tests/bugs/core_4376_test.py +++ b/tests/bugs/core_4376_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4376 FBTEST: bugs.core_4376 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -58,9 +64,10 @@ ^ """ -act = isql_act('db', test_script, substitutions=[('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '')]) +substitutions = [(r'^\s*(-)?At line.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42S02 unsuccessful metadata update -CREATE OR ALTER PROCEDURE SP_TEST failed @@ -68,7 +75,7 @@ -SQL error code = -204 -Table unknown -TEST - -At line 3, column 26 + Statement failed, SQLSTATE = 42S22 unsuccessful metadata update -RECREATE PACKAGE BODY PKG_TEST failed @@ -76,12 +83,28 @@ -SQL error code = -206 -Column unknown -NON_EXISTENT_FIELD - -At line 12, column 16 +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42S02 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."SP_TEST" failed + -Dynamic SQL Error + -SQL error code = -204 + -Table unknown + -"TEST" + + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -RECREATE PACKAGE BODY "PUBLIC"."PKG_TEST" failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -"NON_EXISTENT_FIELD" """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f84e842d8558b6eac6ed6967d25c147b5f66dbcc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 16:54:52 +0300 Subject: [PATCH 0838/1064] Added/Updated tests\bugs\core_4379_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4379_test.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4379_test.py b/tests/bugs/core_4379_test.py index e0f29e74..9e08ac00 100644 --- a/tests/bugs/core_4379_test.py +++ b/tests/bugs/core_4379_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4379 FBTEST: bugs.core_4379 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -114,18 +120,16 @@ act = isql_act('db', test_script, substitutions = [('(--\\s+)?line \\d+, col(umn)? \\d+', '')]) # -- line 2, column 7 -expected_stdout = """ +expected_stdout_5x = """ PLAN (X ORDER T_PK_IDX) PLAN (A NATURAL) NATURAL_READS 20000 INDEXED_READS 39999 - PLAN (C_CUR X ORDER T_PK_IDX) PLAN (C_CUR A NATURAL) PLAN (C_CUR X ORDER T_PK_IDX) NATURAL_READS 20000 INDEXED_READS 39999 - PLAN (C_CUR X ORDER T_PK_IDX) PLAN (C_CUR A NATURAL) PLAN (C_CUR X ORDER T_PK_IDX) @@ -134,9 +138,26 @@ INDEXED_READS 59999 """ +expected_stdout_6x = """ + PLAN ("X" ORDER "PUBLIC"."T_PK_IDX") + PLAN ("A" NATURAL) + NATURAL_READS 20000 + INDEXED_READS 39999 + PLAN ("C_CUR" "X" ORDER "PUBLIC"."T_PK_IDX") + PLAN ("C_CUR" "A" NATURAL) + PLAN ("C_CUR" "X" ORDER "PUBLIC"."T_PK_IDX") + NATURAL_READS 20000 + INDEXED_READS 39999 + PLAN ("C_CUR" "X" ORDER "PUBLIC"."T_PK_IDX") + PLAN ("C_CUR" "A" NATURAL) + PLAN ("C_CUR" "X" ORDER "PUBLIC"."T_PK_IDX") + PLAN ("PUBLIC"."T" INDEX ()) + NATURAL_READS 20000 + INDEXED_READS 59999 +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 9e9e90b4c20eeaf0f340695d491de251614cf0a8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:02:18 +0300 Subject: [PATCH 0839/1064] Added/Updated tests\bugs\core_4381_test.py: Added subst to suppress displaying name of stored procedure: on 6.x it is prefixed by SQL schema and enclosed in quotes. For this test it is enough just to show proper numbers of line and column. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4381_test.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4381_test.py b/tests/bugs/core_4381_test.py index cd5c19d1..0d4974a3 100644 --- a/tests/bugs/core_4381_test.py +++ b/tests/bugs/core_4381_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4381 FBTEST: bugs.core_4381 +NOTES: + [29.06.2025] pzotov + Added subst to suppress displaying name of stored procedure: on 6.x it is prefixed by SQL schema and enclosed in quotes. + For this test it is enough just to show proper numbers of line and column. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,17 +38,17 @@ ^ """ -act = isql_act('db', test_script) +substitutions = [('-At procedure \\S+', 'At procedure')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = 22018 conversion error from string "a" - -At procedure 'P1' line: 3, col: 28 + At procedure line: 3, col: 28 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From b7e209d166a47170989cd44577a4fe64f6baa0b8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:09:14 +0300 Subject: [PATCH 0840/1064] Added/Updated tests\bugs\core_4386_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4386_test.py | 121 ++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/tests/bugs/core_4386_test.py b/tests/bugs/core_4386_test.py index 943180c6..2052e576 100644 --- a/tests/bugs/core_4386_test.py +++ b/tests/bugs/core_4386_test.py @@ -9,32 +9,34 @@ FBTEST: bugs.core_4386 NOTES: [22.11.2021] pcisar - This test requires READ_COMMITTED_NO_RECORD_VERSION transaction to work, which - requires ReadConsistency disabled in FB 4. However, it does not work as expected - because all drop commands pass without exception even with ReadConsistency disabled. - The same happens under 3.0.8 (no errors raised). + This test requires READ_COMMITTED_NO_RECORD_VERSION transaction to work, which + requires ReadConsistency disabled in FB 4. However, it does not work as expected + because all drop commands pass without exception even with ReadConsistency disabled. + The same happens under 3.0.8 (no errors raised). [17.09.2022] pzotov - 1. Test actually must work identical for *every* isolation mode of all possible set. - 2. One need to be very careful with object that attempts to make COMMIT after DROP statement: - if we use custom TPB, start transaction explicitly and 'bind' DDL cursor to this transaction - then we have to run commit *exactly* by this TRANSACTION rather then connection whoch owns it! - See 'tx2.commit()' in the code. If we replace it with 'con2.commit()' then Tx2 will be - *silently* rolled back (!!despite that we issued con.commit() !!) and we will not get any - error messages. I'm not sure whether this correct or no. - Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 - + 1. Test actually must work identical for *every* isolation mode of all possible set. + 2. One need to be very careful with object that attempts to make COMMIT after DROP statement: + if we use custom TPB, start transaction explicitly and 'bind' DDL cursor to this transaction + then we have to run commit *exactly* by this TRANSACTION rather then connection whoch owns it! + See 'tx2.commit()' in the code. If we replace it with 'con2.commit()' then Tx2 will be + *silently* rolled back (!!despite that we issued con.commit() !!) and we will not get any + error messages. I'm not sure whether this correct or no. + Checked on 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.730 [22.08.2024] pzotov - * Changed DDL because of SubQueryConversion config parameter appearance. - We have to AVOID usage of queries which have plan that can be changed when firebird.conf has - SubQueryConversion = true. In that case some index can be excluded from plan and thus - it can be dropped on first iteration of 'for x_isol in tx_isol_lst' loop. This causes unexpected - error 'index not found' for subsequent checks. - * Added check for error message when we try to drop standalone function. - * Assert moved out to the point after loop in order to show whole result in case of some error - (rather than only one message block for some particular x_isol). - * Excluded check of FB 3.x (this version no more changed). - - Checked on 6.0.0.442, 5.0.2.1479, 4.0.6.3142 + * Changed DDL because of SubQueryConversion config parameter appearance. + We have to AVOID usage of queries which have plan that can be changed when firebird.conf has + SubQueryConversion = true. In that case some index can be excluded from plan and thus + it can be dropped on first iteration of 'for x_isol in tx_isol_lst' loop. This causes unexpected + error 'index not found' for subsequent checks. + * Added check for error message when we try to drop standalone function. + * Assert moved out to the point after loop in order to show whole result in case of some error + (rather than only one message block for some particular x_isol). + * Excluded check of FB 3.x (this version no more changed). + Checked on 6.0.0.442, 5.0.2.1479, 4.0.6.3142 + + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -154,215 +156,216 @@ def test_1(act: Action, capsys): print(e.__str__()) print(e.gds_codes) + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' act.expected_stdout = f""" READ_COMMITTED_NO_RECORD_VERSION drop procedure sp_test lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop procedure sp_worker lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop function fn_worker lock conflict on no wait transaction -unsuccessful metadata update - -object FUNCTION "FN_WORKER" is in use + -object FUNCTION {SQL_SCHEMA_PREFIX}"FN_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop view v_test lock conflict on no wait transaction -unsuccessful metadata update - -object VIEW "V_TEST" is in use + -object VIEW {SQL_SCHEMA_PREFIX}"V_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop table test2 lock conflict on no wait transaction -unsuccessful metadata update - -object TABLE "TEST2" is in use + -object TABLE {SQL_SCHEMA_PREFIX}"TEST2" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop index test1_id lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST1_ID" is in use (335544345, 335544351, 335544453) READ_COMMITTED_NO_RECORD_VERSION drop index test2_x lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST2_X" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST2_X" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop procedure sp_test lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop procedure sp_worker lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop function fn_worker lock conflict on no wait transaction -unsuccessful metadata update - -object FUNCTION "FN_WORKER" is in use + -object FUNCTION {SQL_SCHEMA_PREFIX}"FN_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop view v_test lock conflict on no wait transaction -unsuccessful metadata update - -object VIEW "V_TEST" is in use + -object VIEW {SQL_SCHEMA_PREFIX}"V_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop table test2 lock conflict on no wait transaction -unsuccessful metadata update - -object TABLE "TEST2" is in use + -object TABLE {SQL_SCHEMA_PREFIX}"TEST2" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop index test1_id lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST1_ID" is in use (335544345, 335544351, 335544453) READ_COMMITTED_RECORD_VERSION drop index test2_x lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST2_X" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST2_X" is in use (335544345, 335544351, 335544453) SNAPSHOT drop procedure sp_test lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_TEST" is in use (335544345, 335544351, 335544453) SNAPSHOT drop procedure sp_worker lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_WORKER" is in use (335544345, 335544351, 335544453) SNAPSHOT drop function fn_worker lock conflict on no wait transaction -unsuccessful metadata update - -object FUNCTION "FN_WORKER" is in use + -object FUNCTION {SQL_SCHEMA_PREFIX}"FN_WORKER" is in use (335544345, 335544351, 335544453) SNAPSHOT drop view v_test lock conflict on no wait transaction -unsuccessful metadata update - -object VIEW "V_TEST" is in use + -object VIEW {SQL_SCHEMA_PREFIX}"V_TEST" is in use (335544345, 335544351, 335544453) SNAPSHOT drop table test2 lock conflict on no wait transaction -unsuccessful metadata update - -object TABLE "TEST2" is in use + -object TABLE {SQL_SCHEMA_PREFIX}"TEST2" is in use (335544345, 335544351, 335544453) SNAPSHOT drop index test1_id lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST1_ID" is in use (335544345, 335544351, 335544453) SNAPSHOT drop index test2_x lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST2_X" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST2_X" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop procedure sp_test lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_TEST" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop procedure sp_worker lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_WORKER" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop function fn_worker lock conflict on no wait transaction -unsuccessful metadata update - -object FUNCTION "FN_WORKER" is in use + -object FUNCTION {SQL_SCHEMA_PREFIX}"FN_WORKER" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop view v_test lock conflict on no wait transaction -unsuccessful metadata update - -object VIEW "V_TEST" is in use + -object VIEW {SQL_SCHEMA_PREFIX}"V_TEST" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop table test2 lock conflict on no wait transaction -unsuccessful metadata update - -object TABLE "TEST2" is in use + -object TABLE {SQL_SCHEMA_PREFIX}"TEST2" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop index test1_id lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST1_ID" is in use (335544345, 335544351, 335544453) SERIALIZABLE drop index test2_x lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST2_X" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST2_X" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop procedure sp_test lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_TEST" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop procedure sp_worker lock conflict on no wait transaction -unsuccessful metadata update - -object PROCEDURE "SP_WORKER" is in use + -object PROCEDURE {SQL_SCHEMA_PREFIX}"SP_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop function fn_worker lock conflict on no wait transaction -unsuccessful metadata update - -object FUNCTION "FN_WORKER" is in use + -object FUNCTION {SQL_SCHEMA_PREFIX}"FN_WORKER" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop view v_test lock conflict on no wait transaction -unsuccessful metadata update - -object VIEW "V_TEST" is in use + -object VIEW {SQL_SCHEMA_PREFIX}"V_TEST" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop table test2 lock conflict on no wait transaction -unsuccessful metadata update - -object TABLE "TEST2" is in use + -object TABLE {SQL_SCHEMA_PREFIX}"TEST2" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop index test1_id lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST1_ID" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST1_ID" is in use (335544345, 335544351, 335544453) READ_COMMITTED_READ_CONSISTENCY drop index test2_x lock conflict on no wait transaction -unsuccessful metadata update - -object INDEX "TEST2_X" is in use + -object INDEX {SQL_SCHEMA_PREFIX}"TEST2_X" is in use (335544345, 335544351, 335544453) """ From 82b206a9c8865ca9cf68a7c58b207542133cfa37 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:23:55 +0300 Subject: [PATCH 0841/1064] Added/Updated tests\bugs\core_4403_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4403_test.py | 96 ++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/tests/bugs/core_4403_test.py b/tests/bugs/core_4403_test.py index 300972ee..4981e868 100644 --- a/tests/bugs/core_4403_test.py +++ b/tests/bugs/core_4403_test.py @@ -7,12 +7,23 @@ DESCRIPTION: JIRA: CORE-4403 FBTEST: bugs.core_4403 +NOTES: + [29.06.2025] pzotov + Increased min_version to 4.0 because name of column is not shown in old 3.x. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ + set list on; + recreate table t1(id int primary key, x int, y int); recreate table t2(id int primary key, x int, y int); recreate table t3(id int primary key, x int, y int); @@ -32,12 +43,7 @@ ^ set term ;^ commit; -""" - -db = db_factory(init=init_script) -test_script = """ - set list on; set term ^; execute block returns( t1_id int, t1_x int, t1_y int @@ -80,10 +86,6 @@ end ^ - --/******************** - --### 29.05.2015. TODO ### UNCOMMENT LATER, AFTER FIX CORE-4819. CURRENTLY IT LEADS FB TO HANG / CRASH. - - -- Uncomment 06.08.2018: execute block returns(old_y int, new_y int) as begin for @@ -97,60 +99,48 @@ end end ^ - -- ********************/ - set term ;^ commit; set list off; """ -act = isql_act('db', test_script) - -expected_stdout = """ - T1_ID 1 - T1_X 10 - T1_Y 11 - T2_ID 2 - T2_X 10 - T2_Y 22 - T3_ID 3 - T3_X 10 - T3_Y 33 -""" - -# version: 3.0 - -expected_stderr_1 = """ +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_5x = """ + T1_ID 1 + T1_X 10 + T1_Y 11 + T2_ID 2 + T2_X 10 + T2_Y 22 + T3_ID 3 + T3_X 10 + T3_Y 33 Statement failed, SQLSTATE = 42000 - attempted update of read-only column - + attempted update of read-only column CE.X Statement failed, SQLSTATE = 42000 - attempted update of read-only column + attempted update of read-only column CE.Y """ -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - -# version: 4.0 - -expected_stderr_2 = """ +expected_stdout_6x = """ + T1_ID 1 + T1_X 10 + T1_Y 11 + T2_ID 2 + T2_X 10 + T2_Y 22 + T3_ID 3 + T3_X 10 + T3_Y 33 Statement failed, SQLSTATE = 42000 - attempted update of read-only column CE.X - + attempted update of read-only column "CE"."X" Statement failed, SQLSTATE = 42000 - attempted update of read-only column CE.Y + attempted update of read-only column "CE"."Y" """ @pytest.mark.version('>=4.0') -def test_2(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - +def test_1(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f38705d26e9b681d12faa9dce9a4abb01d9ac172 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:32:49 +0300 Subject: [PATCH 0842/1064] Added/Updated tests\bugs\core_4415_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4415_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4415_test.py b/tests/bugs/core_4415_test.py index 47538d0c..55eb9390 100644 --- a/tests/bugs/core_4415_test.py +++ b/tests/bugs/core_4415_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4415 FBTEST: bugs.core_4415 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -21,17 +27,21 @@ -- TR, Sequence: 0, Type: BEFORE CREATE TABLE OR ALTER TABLE OR DROP TABLE OR ... OR , Active // length = 967 characters. """ -act = isql_act('db', test_script, substitutions=[('\\+.*', ''), ('\\=.*', ''), - ('Trigger text.*', '')]) +substitutions = [('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ TR, Sequence: 0, Type: BEFORE ANY DDL STATEMENT, Active as begin end """ +expected_stdout_6x = """ + PUBLIC.TR, Sequence: 0, Type: BEFORE ANY DDL STATEMENT, Active + as begin end +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From c21718b1c0cc6e9cf7ad8b82a1ab43cdc0119d4f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:35:00 +0300 Subject: [PATCH 0843/1064] Added/Updated tests\bugs\core_4447_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4447_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4447_test.py b/tests/bugs/core_4447_test.py index b5166f69..4b20eeff 100644 --- a/tests/bugs/core_4447_test.py +++ b/tests/bugs/core_4447_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4447 FBTEST: bugs.core_4447 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -45,14 +51,18 @@ act = isql_act('db', test_script, substitutions = [('(--\\s+)?line \\d+, col(umn)? \\d+', '')]) -expected_stdout = """ - PLAN (T INDEX (TT_PK_XY)) - PLAN (C TS NATURAL) +expected_stdout_5x = """ + PLAN (T INDEX (TT_PK_XY)) + PLAN (C TS NATURAL) +""" + +expected_stdout_6x = """ + PLAN ("T" INDEX ("PUBLIC"."TT_PK_XY")) + PLAN ("C" "PUBLIC"."TS" NATURAL) """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 4eedc6283a8dbfce09226e9670b68cd503265d40 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:39:48 +0300 Subject: [PATCH 0844/1064] Added/Updated tests\bugs\core_4451_test.py: Suppressed name of table because on 6.x it is prefixed by SQL schema and is enclosed in quotes. For this test it is enough just to show that explained form of plan presents in the trace. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4451_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_4451_test.py b/tests/bugs/core_4451_test.py index d3ab4a2b..3d7c976e 100644 --- a/tests/bugs/core_4451_test.py +++ b/tests/bugs/core_4451_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4451 FBTEST: bugs.core_4451 +NOTES: + [29.06.2025] pzotov + Suppressed name of table because on 6.x it is prefixed by SQL schema and is enclosed in quotes. + For this test it is enough just to show that explained form of plan presents in the trace. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,7 +24,7 @@ db = db_factory(init=init_script) -act = python_act('db', substitutions=[('[ \t]+', ' '), ('[ \t]+[\\d]+[ \t]+ms', '')]) +act = python_act('db', substitutions=[('[ \t]+', ' '), ('[ \t]+[\\d]+[ \t]+ms', ''), ('Table.*', 'Table')]) expected_stdout = """ Select Expression From 568606e38a5ecc6fd69aae9cd13630a82b5910e9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 17:48:17 +0300 Subject: [PATCH 0845/1064] Added/Updated tests\bugs\core_4453_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4453_test.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_4453_test.py b/tests/bugs/core_4453_test.py index 9dec560d..bb283e7f 100644 --- a/tests/bugs/core_4453_test.py +++ b/tests/bugs/core_4453_test.py @@ -5,19 +5,24 @@ ISSUE: 4773 TITLE: Regression: NOT NULL constraint, declared in domain, does not work DESCRIPTION: + Tests that manipulates with NULL fields/domains and check results: + CORE-1518 Adding a non-null restricted column to a populated table renders the table inconsistent + CORE-4453 (Regression: NOT NULL constraint, declared in domain, does not work) + CORE-4725 (Inconsistencies with ALTER DOMAIN and ALTER TABLE with DROP NOT NULL and PRIMARY KEYs) + CORE-4733 (Command "Alter table alter TYPE and makes incorrect assignments in to ZERO / JULIAN_DATE / ASCII(0) for types INT, TIMESTAMP and VARCHAR) JIRA: CORE-4453 FBTEST: bugs.core_4453 + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * init_script = """ - -- Tests that manipulates with NULL fields/domains and check results: - -- CORE-1518 Adding a non-null restricted column to a populated table renders the table inconsistent - -- CORE-4453 (Regression: NOT NULL constraint, declared in domain, does not work) - -- CORE-4725 (Inconsistencies with ALTER DOMAIN and ALTER TABLE with DROP NOT NULL and PRIMARY KEYs) - -- CORE-4733 (Command "Alter table alter TYPE and makes incorrect assignments in to ZERO / JULIAN_DATE / ASCII(0) for types INT, TIMESTAMP and VARCHAR) create domain dm_01 varchar(20) not null; commit; create table t_01(s dm_01, x int); @@ -33,14 +38,18 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 validation error for column "T_01"."S", value "*** null ***" """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."T_01"."S", value "*** null ***" +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 482ac14a649ecf6dc8105321a4603105e88021a6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 18:01:40 +0300 Subject: [PATCH 0846/1064] Added/Updated tests\bugs\core_4468_test.py: Added variable 'PLG_VIEW_NAME' with value depending on major FB version (on 6.x it is prefixed with SQL schema name). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4468_test.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4468_test.py b/tests/bugs/core_4468_test.py index 0c8974b3..3dfaad17 100644 --- a/tests/bugs/core_4468_test.py +++ b/tests/bugs/core_4468_test.py @@ -16,6 +16,11 @@ [15.05.2025] pzotov Removed 'show grants' because its output very 'fragile' and can often change in master branch. It is enough to use custom VIEW ('v_users') to check data. + + [29.06.2025] pzotov + Added variable 'PLG_VIEW_NAME' with value depending on major FB version (on 6.x it is prefixed with SQL schema name). + This variable is substituted in expected output via f-notation. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import locale @@ -23,8 +28,8 @@ from firebird.qa import * substitutions = [('.*delete record.*', 'delete record'), - ('TABLE PLG\\$VIEW_USERS', 'TABLE PLG'), - ('TABLE PLG\\$SRP_VIEW', 'TABLE PLG'), + #('TABLE PLG\\$VIEW_USERS', 'TABLE PLG'), + #('TABLE PLG\\$SRP_VIEW', 'TABLE PLG'), ('-Effective user is.*', '')] db = db_factory() @@ -151,6 +156,9 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): commit; """ + # 29.06.2025: name of view differs depending on major FB vefsion: + PLG_VIEW_NAME = 'PLG$SRP_VIEW' if act.is_version('<6') else '"PLG$SRP"."PLG$SRP_VIEW"' + expected_out = f""" MSG start WHO_AM_I {act.db.user} @@ -267,7 +275,7 @@ def test_1(act: Action, tmp_senior: User, tmp_junior: User): Records affected: 1 Statement failed, SQLSTATE = 28000 delete record - -no permission for DELETE access to TABLE PLG + -no permission for DELETE access to TABLE {PLG_VIEW_NAME} MSG point-8 WHO_AM_I {tmp_senior.name} WHATS_MY_ROLE RDB$ADMIN From 4b230e94f5a0442dbb6659d73c1722f17fc57536 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 18:06:00 +0300 Subject: [PATCH 0847/1064] Added/Updated tests\bugs\core_4470_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4470_test.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_4470_test.py b/tests/bugs/core_4470_test.py index 04ba62a3..03baf9a9 100644 --- a/tests/bugs/core_4470_test.py +++ b/tests/bugs/core_4470_test.py @@ -10,6 +10,12 @@ Replaced PSQL function name 'localtime()' with 'fn_local_time()': first of them became keyword in FB 4.0 JIRA: CORE-4470 FBTEST: bugs.core_4470 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -254,11 +260,16 @@ act = python_act('db') -expected_stdout = """ +expected_stdout_5x = """ METEO WF """ +expected_stdout_6x = """ + PUBLIC.METEO + PUBLIC.WF +""" + fbk_file = temp_file('test.fbk') @pytest.mark.version('>=3.0') @@ -269,6 +280,13 @@ def test_1(act: Action, fbk_file: Path): srv.database.restore(backup=fbk_file, database=act.db.db_path, flags=SrvRestoreFlag.REPLACE) srv.wait() - act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input='show view; show package;') + + test_script = """ + show view; + show package; + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout + From ccd3377e2afa18e2fcdf5e1483f7244553d937c7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 18:53:50 +0300 Subject: [PATCH 0848/1064] Added/Updated tests\bugs\core_4492_test.py: Added branch in defintion of expected output for FB-6x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4492_test.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4492_test.py b/tests/bugs/core_4492_test.py index 1278d0e9..883256b4 100644 --- a/tests/bugs/core_4492_test.py +++ b/tests/bugs/core_4492_test.py @@ -5,21 +5,29 @@ ISSUE: 1566 TITLE: OR/IN predicates for RDB$DBKEY lead to NATURAL plan DESCRIPTION: -NOTES: -[25.11.2017] - Following query will not compile: - select 1 from rdb$relations a join rdb$relations b using ( rdb$db_key ); - Statement failed, SQLSTATE = 42000 / -Token unknown / -rdb$db_key ==> Why ? - Sent letter to dimitr, 25.11.2017 22:42. Waiting for reply. -[27.12.2017] seems that this note will remain unresolved for undef. time. JIRA: CORE-4492 FBTEST: bugs.core_4492 NOTES: + [25.11.2017] + Following query will not compile: + select 1 from rdb$relations a join rdb$relations b using ( rdb$db_key ); + Statement failed, SQLSTATE = 42000 / -Token unknown / -rdb$db_key ==> Why ? + Sent letter to dimitr, 25.11.2017 22:42. Waiting for reply. + + [27.12.2017] + Seems that this note will remain unresolved for undef. time. + [07.04.2022] pzotov FB 5.0.0.455 and later: data sources with equal cardinality now present in the HASH plan in order they are specified in the query. Reversed order was used before this build. Because of this, two cases of expected stdout must be taken in account, see variables 'fb3x_checked_stdout' and 'fb5x_checked_stdout'. + + [29.06.2025] pzotov + Added branch in defintion of expected output for FB-6x. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + """ import pytest @@ -74,9 +82,17 @@ PLAN HASH (VU_A RDB$RELATIONS NATURAL, VU_A RDB$RELATIONS NATURAL, VU_B RDB$RELATIONS NATURAL, VU_B RDB$RELATIONS NATURAL) """ +fb6x_checked_stdout = """ + PLAN ("RR0" INDEX ()) + PLAN ("RR1" INDEX ()) + PLAN ("VU" "SYSTEM"."RDB$RELATIONS" INDEX (), "VU" "SYSTEM"."RDB$RELATIONS" INDEX ()) + PLAN JOIN ("RR_A" NATURAL, "RR_B" INDEX ()) + PLAN HASH ("VU_A" "SYSTEM"."RDB$RELATIONS" NATURAL, "VU_A" "SYSTEM"."RDB$RELATIONS" NATURAL, "VU_B" "SYSTEM"."RDB$RELATIONS" NATURAL, "VU_B" "SYSTEM"."RDB$RELATIONS" NATURAL) +""" + @pytest.mark.version('>=3.0.3') def test_1(act: Action): - act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout - act.execute() + act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 31f582df061c1411ad2f104310e6a1ef7dda3182 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 18:57:55 +0300 Subject: [PATCH 0849/1064] Added/Updated tests\bugs\core_4498_test.py: Added subst to suppress displaying name of table: on 6.x it is prefixed by SQL schema and enclosed in quotes. For this test it is enough just to show proper starting part of line with explained plan and check that no error occurs. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4498_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_4498_test.py b/tests/bugs/core_4498_test.py index 73f80a42..25cc9ea8 100644 --- a/tests/bugs/core_4498_test.py +++ b/tests/bugs/core_4498_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4498 FBTEST: bugs.core_4498 +NOTES: + [29.06.2025] pzotov + Added subst to suppress displaying name of table: on 6.x it is prefixed by SQL schema and enclosed in quotes. + For this test it is enough just to show proper starting part of line with explained plan and check that no error occurs. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -19,7 +25,7 @@ select 1 from rdb$relations where rdb$db_key = cast('1234' as char(8) character set octets); """ -act = isql_act('db', test_script) +act = isql_act('db', test_script, substitutions = [('Table .*', 'Table')]) expected_stdout = """ Select Expression From 8d72f1aacfe08a0a50a13885b13b3abff4302da2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:02:49 +0300 Subject: [PATCH 0850/1064] Added/Updated tests\bugs\core_4524_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4524_test.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4524_test.py b/tests/bugs/core_4524_test.py index 4fc4c318..6b014269 100644 --- a/tests/bugs/core_4524_test.py +++ b/tests/bugs/core_4524_test.py @@ -27,8 +27,11 @@ [21.09.2022] pzotov Test reads settings that are COMMON for all encryption-related tests and stored in act.files_dir/test_config.ini. QA-plugin prepares this by defining dictionary with name QA_GLOBALS which reads settings via ConfigParser mechanism. - Checked on Linux and Windows: 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS) + + [29.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import os import binascii @@ -268,15 +271,18 @@ def test_1(act_src: Action, act_res: Action, tmp_fbk:Path, capsys): # Final check: ensure that sequences have proper values: ############## - act_res.expected_stdout = """ - Generator GEN_7FFFFFFF, current value: 2147483646, initial value: 2147483647, increment: 1 - Generator GEN_BA0BAB, current value: 12192682, initial value: 12192683, increment: 1 - Generator GEN_BADF00D, current value: 195948556, initial value: 195948557, increment: 1 - Generator GEN_C0FFEE, current value: 12648429, initial value: 12648430, increment: 1 - Generator GEN_CACA0, current value: 830623, initial value: 830624, increment: 1 - Generator GEN_DEC0DE, current value: 14598365, initial value: 14598366, increment: 1 - Generator GEN_DECADE, current value: 14600925, initial value: 14600926, increment: 1 + SQL_SCHEMA_PREFIX = '' if act_res.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + Generator {SQL_SCHEMA_PREFIX}GEN_7FFFFFFF, current value: 2147483646, initial value: 2147483647, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_BA0BAB, current value: 12192682, initial value: 12192683, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_BADF00D, current value: 195948556, initial value: 195948557, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_C0FFEE, current value: 12648429, initial value: 12648430, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_CACA0, current value: 830623, initial value: 830624, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_DEC0DE, current value: 14598365, initial value: 14598366, increment: 1 + Generator {SQL_SCHEMA_PREFIX}GEN_DECADE, current value: 14600925, initial value: 14600926, increment: 1 """ + + act_res.expected_stdout = expected_stdout act_res.isql(switches = ['-q'], input = 'show sequ;', combine_output = True, io_enc = locale.getpreferredencoding()) assert act_res.clean_stdout == act_res.clean_expected_stdout act_res.reset() From 6e807e138e4c749df3261792bcd11681ff49375c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:04:52 +0300 Subject: [PATCH 0851/1064] Added/Updated tests\bugs\core_4528_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4528_test.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4528_test.py b/tests/bugs/core_4528_test.py index b43c82f5..777f9c05 100644 --- a/tests/bugs/core_4528_test.py +++ b/tests/bugs/core_4528_test.py @@ -125,9 +125,19 @@ PLAN HASH (R TN NATURAL, S TN NATURAL) """ +fb6x_checked_stdout = """ + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL, "T" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL, "T" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL, "T" "PUBLIC"."TN" NATURAL, "U" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL) + PLAN HASH ("R" "PUBLIC"."TN" NATURAL, "S" "PUBLIC"."TN" NATURAL) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout - act.execute() + act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From f9b1e2d4d843c7040f7b6f305922e269e87176cd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:06:38 +0300 Subject: [PATCH 0852/1064] Added/Updated tests\bugs\core_4529_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4529_test.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_4529_test.py b/tests/bugs/core_4529_test.py index d5f9ddc4..2426cf60 100644 --- a/tests/bugs/core_4529_test.py +++ b/tests/bugs/core_4529_test.py @@ -36,15 +36,20 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (T ORDER T_X_DESC) PLAN (T ORDER T_X_DESC) PLAN (T ORDER T_C_DESC) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" ORDER "PUBLIC"."T_X_DESC") + PLAN ("PUBLIC"."T" ORDER "PUBLIC"."T_X_DESC") + PLAN ("PUBLIC"."T" ORDER "PUBLIC"."T_C_DESC") +""" + @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From fecc5cb8a989ecd5b89f8b49386596bc804b0763 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:08:16 +0300 Subject: [PATCH 0853/1064] Added/Updated tests\bugs\core_4530_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4530_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4530_test.py b/tests/bugs/core_4530_test.py index bfced314..b56dd28e 100644 --- a/tests/bugs/core_4530_test.py +++ b/tests/bugs/core_4530_test.py @@ -9,6 +9,12 @@ and thus performance JIRA: CORE-4530 FBTEST: bugs.core_4530 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -37,14 +43,18 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) - PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) +expected_stdout_5x = """ + PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) + PLAN JOIN (X A ORDER T_PK_IDX, Z INDEX ()) +""" + +expected_stdout_6x = """ + PLAN JOIN ("X" "A" ORDER "PUBLIC"."T_PK_IDX", "Z" INDEX ()) + PLAN JOIN ("X" "A" ORDER "PUBLIC"."T_PK_IDX", "Z" INDEX ()) """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 9abef8b78b3e03bfde246c665f63477c4c23f63f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:09:48 +0300 Subject: [PATCH 0854/1064] Added/Updated tests\bugs\core_4539_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4539_test.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_4539_test.py b/tests/bugs/core_4539_test.py index b590c041..40aafc7b 100644 --- a/tests/bugs/core_4539_test.py +++ b/tests/bugs/core_4539_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4539 FBTEST: bugs.core_4539 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -41,13 +47,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (H NATURAL, C INDEX (COLOR_NAME)) """ +expected_stdout_6x = """ + PLAN JOIN ("H" NATURAL, "C" INDEX ("PUBLIC"."COLOR_NAME")) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 8af759c9941f5d5bfde3fb253bdd6bd1a5677cde Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:12:25 +0300 Subject: [PATCH 0855/1064] Added/Updated tests\bugs\core_4555_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4555_test.py | 41 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_4555_test.py b/tests/bugs/core_4555_test.py index ee1531db..0289d49e 100644 --- a/tests/bugs/core_4555_test.py +++ b/tests/bugs/core_4555_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4555 FBTEST: bugs.core_4555 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,31 +55,38 @@ act = isql_act('db', test_script, substitutions=[('=.*', ''), ('line:\\s[0-9]+,', 'line: x'), ('col:\\s[0-9]+', 'col: y')]) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE + unsuccessful metadata update + -CREATE EXCEPTION USER_EXCEPTION failed + -exception 1 + -DDL_EXCEPTION + -You have no right to create exceptions. Learn DDL triggers first! + -At trigger 'T_DDL' line: x col: y RDB$EXCEPTION_NAME DDL_EXCEPTION RDB$MESSAGE You have no right to create exceptions. Learn DDL triggers first! - RDB$EXCEPTION_NAME USER_EXCEPTION RDB$MESSAGE Invalid remainder found for case-2. - Records affected: 2 """ -expected_stderr = """ - Statement failed, SQLSTATE = HY000 +expected_stdout_6x = """ + Statement failed, SQLSTATE unsuccessful metadata update - -CREATE EXCEPTION USER_EXCEPTION failed + -CREATE EXCEPTION "PUBLIC"."USER_EXCEPTION" failed -exception 1 - -DDL_EXCEPTION + -"PUBLIC"."DDL_EXCEPTION" -You have no right to create exceptions. Learn DDL triggers first! - -At trigger 'T_DDL' line: 6, col: 9 + -At trigger "PUBLIC"."T_DDL" line: x col: y + RDB$EXCEPTION_NAME DDL_EXCEPTION + RDB$MESSAGE You have no right to create exceptions. Learn DDL triggers first! + RDB$EXCEPTION_NAME USER_EXCEPTION + RDB$MESSAGE Invalid remainder found for case-2. + Records affected: 2 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From dd017cae5ae8cd5ff851df236d5b579ef0fbf74c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:17:10 +0300 Subject: [PATCH 0856/1064] Added/Updated tests\bugs\core_4557_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4557_test.py | 49 +++++++++++++++++------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_4557_test.py b/tests/bugs/core_4557_test.py index c2452f52..92f4f678 100644 --- a/tests/bugs/core_4557_test.py +++ b/tests/bugs/core_4557_test.py @@ -3,56 +3,53 @@ """ ID: issue-1578 ISSUE: 1578 -TITLE: FB 3.0 crashes on EXIT (or QUIT) command if use UTF8-collation + create domain - based on it + issue SHOW DOMAIN +TITLE: FB 3.0 crashes on EXIT (or QUIT) command if use UTF8-collation + create domain based on it + issue SHOW DOMAIN DESCRIPTION: JIRA: CORE-4557 FBTEST: bugs.core_4557 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ +db = db_factory() + +test_script = """ create collation name_coll for utf8 from unicode CASE INSENSITIVE; create collation nums_coll for utf8 from unicode CASE INSENSITIVE 'NUMERIC-SORT=1'; commit; create domain dm_name as varchar(80) character set utf8 collate name_coll; create domain dm_nums as varchar(20) character set utf8 collate nums_coll; commit; -""" - -db = db_factory(init=init_script) - -test_script = """ show domain; -- FB crashes if this will be uncommented exit; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -# version: 3.0 - -expected_stdout_1 = """ - DM_NAME DM_NUMS +expected_stdout_3x = """ + DM_NAME DM_NUMS """ -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout_1 - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - -# version: 4.0 - -expected_stdout_2 = """ +expected_stdout_5x = """ DM_NAME DM_NUMS """ -@pytest.mark.version('>=4.0') +expected_stdout_6x = """ + PUBLIC.DM_NAME + PUBLIC.DM_NUMS +""" + +@pytest.mark.version('>=3.0') def test_2(act: Action): - act.expected_stdout = expected_stdout_2 - act.execute() + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 33a0e843e85120895877b7ef0772d7a26b6d94d3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:18:34 +0300 Subject: [PATCH 0857/1064] Updated tests\bugs\core_4572_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4572_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4572_test.py b/tests/bugs/core_4572_test.py index b23c285b..19afb9ac 100644 --- a/tests/bugs/core_4572_test.py +++ b/tests/bugs/core_4572_test.py @@ -59,12 +59,14 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 07001 - Parameter mismatch for function FN_MULTIPLIER + Parameter mismatch for function "PUBLIC"."FN_MULTIPLIER" -Parameter A_TIMES has no default value and was not specified or was specified with DEFAULT + Statement failed, SQLSTATE = 07001 - Parameter mismatch for procedure SP_MULTIPLIER + Parameter mismatch for procedure "PUBLIC"."SP_MULTIPLIER" -Parameter A_TIMES has no default value and was not specified or was specified with DEFAULT """ + @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 0d224274997eb3cda1ed21e9b07dc075586ad16c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sun, 29 Jun 2025 19:21:11 +0300 Subject: [PATCH 0858/1064] Added/Updated tests\bugs\core_4585_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4585_test.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_4585_test.py b/tests/bugs/core_4585_test.py index f07e014c..74e8eef7 100644 --- a/tests/bugs/core_4585_test.py +++ b/tests/bugs/core_4585_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4585 FBTEST: bugs.core_4585 +NOTES: + [29.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -25,23 +31,25 @@ select * from test; """ +substitutions = [('[ \t]+', ' ')] act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 23000 + Operation violates CHECK constraint TEST_X_CHK on view or table TEST + -At trigger 'CHECK_1' X 1 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 23000 - Operation violates CHECK constraint TEST_X_CHK on view or table TEST - -At trigger 'CHECK_1' + Operation violates CHECK constraint "TEST_X_CHK" on view or table "PUBLIC"."TEST" + -At trigger "PUBLIC"."CHECK_1" + X 1 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 129faa9627c993fb8b24d4165d20f35c75dbaa41 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 11:58:39 +0300 Subject: [PATCH 0859/1064] Added/Updated tests\bugs\core_4484_test.py: Checked on 6.0.0.881; 5.0.3.1668. --- tests/bugs/core_4484_test.py | 61 +++++++++++++++++------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/tests/bugs/core_4484_test.py b/tests/bugs/core_4484_test.py index 0507c0b6..76462b1c 100644 --- a/tests/bugs/core_4484_test.py +++ b/tests/bugs/core_4484_test.py @@ -4,10 +4,14 @@ ID: issue-4804 ISSUE: 4804 TITLE: Description (COMMENT ON) for package procedures and functions, and its parameters -DESCRIPTION: - Test verifies ability to store comments and also to encode them in UTF8 +DESCRIPTION: Test verifies ability to store comments and also to encode them in UTF8 JIRA: CORE-4484 FBTEST: bugs.core_4484 +NOTES: + [30.06.2025] pzotov + Regression was found in FB 6.x. Fixed in: + https://github.com/FirebirdSQL/firebird/commit/f693bf4e72915534a0d45e9c4eec7a9f1959d2ee + Checked on 6.0.0.881; 5.0.3.1668 """ import pytest @@ -102,35 +106,29 @@ act = isql_act('db', test_script, substitutions=[('TEXT_BLOB.*', '')]) expected_stdout = """ - DESCR_FOR_WHAT package itself - OBJ_NAME PG_TEST - TEXT_BLOB 0:3 - MITÄ TÄMÄN - - DESCR_FOR_WHAT package proc - OBJ_NAME SP_TEST - TEXT_BLOB 0:6 - ÁÉÍÓÚÝ - - DESCR_FOR_WHAT package func - OBJ_NAME FN_TEST - TEXT_BLOB 0:9 - ÂÊÎÔÛ - - DESCR_FOR_WHAT package proc pars - OBJ_NAME I_X - TEXT_BLOB 0:c - ÃÑÕ ÄËÏÖÜŸ - - DESCR_FOR_WHAT package proc pars - OBJ_NAME O_Z - TEXT_BLOB 0:f - ÇŠ ΔΘΛΞΣΨΩ - - DESCR_FOR_WHAT package func args - OBJ_NAME I_X - TEXT_BLOB 0:12 - ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ + DESCR_FOR_WHAT package itself + OBJ_NAME PG_TEST + MITÄ TÄMÄN + + DESCR_FOR_WHAT package proc + OBJ_NAME SP_TEST + ÁÉÍÓÚÝ + + DESCR_FOR_WHAT package func + OBJ_NAME FN_TEST + ÂÊÎÔÛ + + DESCR_FOR_WHAT package proc pars + OBJ_NAME I_X + ÃÑÕ ÄËÏÖÜŸ + + DESCR_FOR_WHAT package proc pars + OBJ_NAME O_Z + ÇŠ ΔΘΛΞΣΨΩ + + DESCR_FOR_WHAT package func args + OBJ_NAME I_X + ĄĘŁŹŻ ЙЁ ЊЋЏ ĂŞŢ """ @pytest.mark.version('>=3.0') @@ -138,4 +136,3 @@ def test_1(act: Action): act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From ddb52b6ca58749eefc832666ac7b9a9ee83b8d49 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 13:43:29 +0300 Subject: [PATCH 0860/1064] Added/Updated tests\bugs\core_4653_test.py: see notes. --- tests/bugs/core_4653_test.py | 60 ++++++++++++------------------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/tests/bugs/core_4653_test.py b/tests/bugs/core_4653_test.py index 9c983b7e..de662f2f 100644 --- a/tests/bugs/core_4653_test.py +++ b/tests/bugs/core_4653_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-4653 FBTEST: bugs.core_4653 +NOTES: + [30.06.2025] pzotov + Part of call stack ('At procedure line X col Y') must be supressed because its length is limited to 1024 characters + and number of lines (together with interrupting marker '...') depends on length of procedure name that is called recursively. + Difference of transactions before and after call to recursive SP must be checked to be sure that there was no crash. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,57 +58,30 @@ -- Old stderr: -- Statement failed, SQLSTATE = HY001 -- Stack overflow. The resource requirements of the runtime stack have exceeded the memory available to it. + set list on; + set term ^; + execute block as + begin + rdb$set_context('USER_TRANSACTION', 'INIT_TX', current_transaction); + end ^ + set term ;^ select * from p01(1); + select current_transaction - cast( rdb$get_context('USER_TRANSACTION', 'INIT_TX') as int) as tx_diff from rdb$database; """ -act = isql_act('db', test_script, substitutions=[('=.*', ''), ('line.*', ''), ('col.*', '')]) +substitutions = [ ('^((?!(SQLSTATE|Too many concurrent executions|TX_DIFF)).)*$', ''), ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - Z - ============ -""" - -expected_stderr = """ Statement failed, SQLSTATE = 54001 Too many concurrent executions of the same request - -At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At procedure 'P02' line: 3, col: 3 - At procedure 'P03' line: 3, col: 3 - At p... + TX_DIFF 0 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4d63786a72b0216a8d4ae4951aefa40dec614774 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 13:50:23 +0300 Subject: [PATCH 0861/1064] Added/Updated tests\bugs\core_4665_test.py: Removed 'set plan on' because this test must check only result of query (data). Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4665_test.py | 185 +++++++++++++++++++++++++---------- 1 file changed, 133 insertions(+), 52 deletions(-) diff --git a/tests/bugs/core_4665_test.py b/tests/bugs/core_4665_test.py index 54d62973..49099f5d 100644 --- a/tests/bugs/core_4665_test.py +++ b/tests/bugs/core_4665_test.py @@ -3,11 +3,15 @@ """ ID: issue-1602 ISSUE: 1602 -TITLE: Wrong result when use "where STARTING WITH <:value> ORDER BY " - and field_C is leading part of compound index key: { field_C, field_N } +TITLE: Wrong result when use "where STARTING WITH <:value> ORDER BY " and field_C is leading part of compound index key: { field_C, field_N } DESCRIPTION: JIRA: CORE-4665 FBTEST: bugs.core_4665 +NOTES: + [30.06.2025] pzotov + Removed 'set plan on' because this test must check only result of query (data). + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,6 +20,7 @@ db = db_factory() test_script = """ + set list on; recreate table test (id int, unit varchar(10), y int, z int); commit; delete from test; @@ -34,18 +39,15 @@ create index test_unit_y_asc on test( unit, y ); commit; - set plan on; - - select id, t.unit, t.y, t.z + select 'point-1' msg, id, t.unit, t.y, t.z from test t where t.unit||'' starting with 'foo' order by t.y||''; - select id, t.unit, t.y, t.z + select 'point-2' msg, id, t.unit, t.y, t.z from test t where t.unit starting with 'foo' order by t.y; - set plan off; commit; drop index test_unit_y_asc; @@ -54,62 +56,141 @@ create descending index test_unit_y_desc on test( unit, y); commit; - set plan on; - select id, t.unit, t.y, t.z + select 'point-3' msg, id, t.unit, t.y, t.z from test t where t.unit starting with 'foo' order by t.y; - set plan off; """ -act = isql_act('db', test_script, substitutions=[('=.*', '')]) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - PLAN SORT (T NATURAL) - - ID UNIT Y Z - ============ ========== ============ ============ - 8 fooo 1 22222 - 7 fooo 11 2222 - 6 fooo 111 222 - 5 fooo 1111 22 - 4 foo 3333 17682 - 3 foo 5555 21822 - 2 foo 8888 22520 - 1 foo 9999 23636 - - - PLAN SORT (T INDEX (TEST_UNIT_Y_ASC)) - - ID UNIT Y Z - ============ ========== ============ ============ - 8 fooo 1 22222 - 7 fooo 11 2222 - 6 fooo 111 222 - 5 fooo 1111 22 - 4 foo 3333 17682 - 3 foo 5555 21822 - 2 foo 8888 22520 - 1 foo 9999 23636 - - - PLAN SORT (T INDEX (TEST_UNIT_Y_DESC)) - - ID UNIT Y Z - ============ ========== ============ ============ - 8 fooo 1 22222 - 7 fooo 11 2222 - 6 fooo 111 222 - 5 fooo 1111 22 - 4 foo 3333 17682 - 3 foo 5555 21822 - 2 foo 8888 22520 - 1 foo 9999 23636 + MSG point-1 + ID 8 + UNIT fooo + Y 1 + Z 22222 + MSG point-1 + ID 7 + UNIT fooo + Y 11 + Z 2222 + MSG point-1 + ID 6 + UNIT fooo + Y 111 + Z 222 + MSG point-1 + ID 5 + UNIT fooo + Y 1111 + Z 22 + MSG point-1 + ID 4 + UNIT foo + Y 3333 + Z 17682 + MSG point-1 + ID 3 + UNIT foo + Y 5555 + Z 21822 + MSG point-1 + ID 2 + UNIT foo + Y 8888 + Z 22520 + MSG point-1 + ID 1 + UNIT foo + Y 9999 + Z 23636 + MSG point-2 + ID 8 + UNIT fooo + Y 1 + Z 22222 + MSG point-2 + ID 7 + UNIT fooo + Y 11 + Z 2222 + MSG point-2 + ID 6 + UNIT fooo + Y 111 + Z 222 + MSG point-2 + ID 5 + UNIT fooo + Y 1111 + Z 22 + MSG point-2 + ID 4 + UNIT foo + Y 3333 + Z 17682 + MSG point-2 + ID 3 + UNIT foo + Y 5555 + Z 21822 + MSG point-2 + ID 2 + UNIT foo + Y 8888 + Z 22520 + MSG point-2 + ID 1 + UNIT foo + Y 9999 + Z 23636 + MSG point-3 + ID 8 + UNIT fooo + Y 1 + Z 22222 + MSG point-3 + ID 7 + UNIT fooo + Y 11 + Z 2222 + MSG point-3 + ID 6 + UNIT fooo + Y 111 + Z 222 + MSG point-3 + ID 5 + UNIT fooo + Y 1111 + Z 22 + MSG point-3 + ID 4 + UNIT foo + Y 3333 + Z 17682 + MSG point-3 + ID 3 + UNIT foo + Y 5555 + Z 21822 + MSG point-3 + ID 2 + UNIT foo + Y 8888 + Z 22520 + MSG point-3 + ID 1 + UNIT foo + Y 9999 + Z 23636 """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From cb077625dee3b85ed6f9cb680ea1558f84e2dda2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 13:53:34 +0300 Subject: [PATCH 0862/1064] Added/Updated tests\bugs\core_4673_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4673_test.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_4673_test.py b/tests/bugs/core_4673_test.py index f9a4a43e..a8b5d446 100644 --- a/tests/bugs/core_4673_test.py +++ b/tests/bugs/core_4673_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4673 FBTEST: bugs.core_4673 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -47,9 +51,10 @@ select count(*) from tc where '' || lpad('' || tc.z_expr, 10, 0) between '0000000302' and '0000000302'; """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TC INDEX (TC_LPAD_Z_NOEX), TC NATURAL, TC INDEX (TC_LPAD_Z_EXPR), TC NATURAL) CHECK_CNT 1 CHECK_CNT 1 @@ -57,9 +62,16 @@ CHECK_CNT 1 """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TC" INDEX ("PUBLIC"."TC_LPAD_Z_NOEX"), "PUBLIC"."TC" NATURAL, "PUBLIC"."TC" INDEX ("PUBLIC"."TC_LPAD_Z_EXPR"), "PUBLIC"."TC" NATURAL) + CHECK_CNT 1 + CHECK_CNT 1 + CHECK_CNT 1 + CHECK_CNT 1 +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From feca6cf9109f15f05cbc048c36e8685700d7609f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:13:34 +0300 Subject: [PATCH 0863/1064] Added/Updated tests\bugs\core_4694_test.py: Removed 'set plan on' because this test must check only absense of erors. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4694_test.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4694_test.py b/tests/bugs/core_4694_test.py index 5cb500f9..f59d77c3 100644 --- a/tests/bugs/core_4694_test.py +++ b/tests/bugs/core_4694_test.py @@ -3,8 +3,7 @@ """ ID: issue-5002 ISSUE: 5002 -TITLE: "Column unknown" error while preparing a recursive query if the recursive part - contains ALIASED datasource in the join with anchor table +TITLE: "Column unknown" error while preparing a recursive query if the recursive part contains ALIASED datasource in the join with anchor table DESCRIPTION: JIRA: CORE-4694 FBTEST: bugs.core_4694 @@ -22,8 +21,6 @@ ); commit; - set planonly; - with recursive r as ( select c.xcall_id @@ -46,12 +43,11 @@ act = isql_act('db', test_script) expected_stdout = """ - PLAN (R C NATURAL, R C NATURAL) """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 3a578ac88235a1902c78f04407b4ce4480b4d3b4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:20:39 +0300 Subject: [PATCH 0864/1064] Added/Updated tests\bugs\core_4702_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4702_test.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_4702_test.py b/tests/bugs/core_4702_test.py index bc5860eb..ef68ce36 100644 --- a/tests/bugs/core_4702_test.py +++ b/tests/bugs/core_4702_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4702 FBTEST: bugs.core_4702 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -90,13 +96,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (TRIAL INDEX (IDX_BYDATE), PRIZE INDEX (PK_PRIZE), TRIAL_LINE INDEX (FK_TRIAL_LINE_TRIAL)) """ +expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."TRIAL" INDEX ("PUBLIC"."IDX_BYDATE"), "PUBLIC"."PRIZE" INDEX ("PUBLIC"."PK_PRIZE"), "PUBLIC"."TRIAL_LINE" INDEX ("PUBLIC"."FK_TRIAL_LINE_TRIAL")) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 70d2b29be4d25fa1dc82e9ca6bf0dc54555a5b83 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:31:21 +0300 Subject: [PATCH 0865/1064] Added/Updated tests\bugs\core_4707_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4707_test.py | 73 ++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_4707_test.py b/tests/bugs/core_4707_test.py index a196647f..d99cb1b0 100644 --- a/tests/bugs/core_4707_test.py +++ b/tests/bugs/core_4707_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4707 FBTEST: bugs.core_4707 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -43,33 +49,14 @@ db = db_factory(init=init_script) -act = python_act('db', substitutions=[('[\\d]{2}:[\\d]{2}:[\\d]{2}.[\\d]{2}', ''), - ('Relation [\\d]{3,4}', 'Relation')]) - -expected_stdout = """ - ISQL_MSG Starting EB with infinite pause. - 08:37:01.14 Validation started - 08:37:01.15 Relation 128 (TEST1) - 08:37:02.15 Acquire relation lock failed - 08:37:02.15 Relation 128 (TEST1) : 1 ERRORS found - 08:37:02.15 Relation 129 (TEST2) - 08:37:02.15 process pointer page 0 of 1 - 08:37:02.15 Index 1 (TEST2_PK) - 08:37:02.15 Index 2 (TEST2_S) - 08:37:02.15 Index 3 (TEST2_C) - 08:37:02.15 Index 4 (TEST2_T) - 08:37:02.17 Relation 129 (TEST2) is ok - 08:37:02.17 Relation 130 (TEST3) - 08:37:03.17 Acquire relation lock failed - 08:37:03.17 Relation 130 (TEST3) : 1 ERRORS found - 08:37:03.17 Validation finished -""" +substitutions=[ ('\\d{2}:\\d{2}:\\d{2}.\\d{2}', ''), ('Relation \\d{3,4}', 'Relation') ] +act = python_act('db', substitutions = substitutions) hang_script_file = temp_file('hang_script.sql') hang_output = temp_file('hang_script.out') @pytest.mark.es_eds -@pytest.mark.version('>=2.5.5') +@pytest.mark.version('>=3.0') def test_1(act: Action, hang_script_file: Path, hang_output: Path, capsys, request): # Fializer for FB4 def drop_connections(): @@ -125,6 +112,46 @@ def drop_connections(): # print(hang_output.read_text()) print(act.stdout) - act.expected_stdout = expected_stdout + + + expected_stdout_5x = """ + ISQL_MSG Starting EB with infinite pause. + Validation started + Relation (TEST1) + Acquire relation lock failed + Relation (TEST1) : 1 ERRORS found + Relation (TEST2) + process pointer page 0 of 1 + Index 1 (TEST2_PK) + Index 2 (TEST2_S) + Index 3 (TEST2_C) + Index 4 (TEST2_T) + Relation (TEST2) is ok + Relation (TEST3) + Acquire relation lock failed + Relation (TEST3) : 1 ERRORS found + Validation finished + """ + + expected_stdout_6x = """ + ISQL_MSG Starting EB with infinite pause. + Validation started + Relation ("PUBLIC"."TEST1") + Acquire relation lock failed + Relation ("PUBLIC"."TEST1") : 1 ERRORS found + Relation ("PUBLIC"."TEST2") + process pointer page 0 of 1 + Index 1 ("PUBLIC"."TEST2_PK") + Index 2 ("PUBLIC"."TEST2_S") + Index 3 ("PUBLIC"."TEST2_C") + Index 4 ("PUBLIC"."TEST2_T") + Relation ("PUBLIC"."TEST2") is ok + Relation ("PUBLIC"."TEST3") + Acquire relation lock failed + Relation ("PUBLIC"."TEST3") : 1 ERRORS found + Validation finished + """ + + 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 From 1460e5df0a234c3eb1b9abf337ffd979df5337aa Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:37:38 +0300 Subject: [PATCH 0866/1064] Added/Updated tests\bugs\core_4725_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4725_test.py | 122 ++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 53 deletions(-) diff --git a/tests/bugs/core_4725_test.py b/tests/bugs/core_4725_test.py index 4352efbd..6075b987 100644 --- a/tests/bugs/core_4725_test.py +++ b/tests/bugs/core_4725_test.py @@ -13,6 +13,12 @@ See https://github.com/FirebirdSQL/firebird/pull/8202 Commit (05-aug-2024 13:45): https://github.com/FirebirdSQL/firebird/commit/0cc8de396a3c2bbe13b161ecbfffa8055e7b4929 + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -185,95 +191,105 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TEST00 failed + -action cancelled by trigger (2) to preserve data integrity + -Column used in a PRIMARY constraint must be NOT NULL. INFO_00 After try to drop NN on FIELD, NN was added by ALTER SET NOT NULL X INTEGER Not Null CONSTRAINT T_PK: - Primary key (X) - + Primary key (X) + Statement failed, SQLSTATE = 27000 + unsuccessful metadata update + -ALTER TABLE TEST01 failed + -action cancelled by trigger (2) to preserve data integrity + -Column used in a PRIMARY constraint must be NOT NULL. INFO_01 After try to drop NN on FIELD, NN was added directly in CREATE TABLE ( not null) X (DM_01) INTEGER Not Null CONSTRAINT TEST01_PK: - Primary key (X) - + Primary key (X) INFO_02 After try to drop NN on FIELD, NN was inherited from DOMAIN X (DM_02) INTEGER Not Null CONSTRAINT TEST02_PK: - Primary key (X) - + Primary key (X) + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN DM_03 failed + -Domain used in the PRIMARY KEY constraint of table TEST03 must be NOT NULL INFO_03 After try to drop NN on DOMAIN but dependent table exists DM_03 INTEGER Not Null X (DM_03) INTEGER Not Null CONSTRAINT TEST03_PK: - Primary key (X) - + Primary key (X) INFO_04 After try to drop NN on FIELD based on not-null domain, but NN was also specified in the field DDL X (DM_04) INTEGER Not Null CONSTRAINT TEST04_PK: - Primary key (X) - + Primary key (X) + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field X of table TEST05 NOT NULL because there are NULLs present INFO_05 After try to set NN on DOMAIN when at least one table exists with NULL in its data DM_05 INTEGER Nullable - INFO_06 After try to set NN on DOMAIN when NO table exists with NULL in its data DM_06 INTEGER Not Null -""" - -expected_stderr_5x = """ - Statement failed, SQLSTATE = 27000 - unsuccessful metadata update - -ALTER TABLE TEST00 failed - -action cancelled by trigger (2) to preserve data integrity - -Column used in a PRIMARY constraint must be NOT NULL. - - Statement failed, SQLSTATE = 27000 - unsuccessful metadata update - -ALTER TABLE TEST01 failed - -action cancelled by trigger (2) to preserve data integrity - -Column used in a PRIMARY constraint must be NOT NULL. - - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -ALTER DOMAIN DM_03 failed - -Domain used in the PRIMARY KEY constraint of table TEST03 must be NOT NULL - - Statement failed, SQLSTATE = 22006 - unsuccessful metadata update - -Cannot make field X of table TEST05 NOT NULL because there are NULLs present - Statement failed, SQLSTATE = 23000 validation error for column "TEST06"."X", value "*** null ***" """ -expected_stderr_6x = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -ALTER TABLE TEST00 failed + -ALTER TABLE "PUBLIC"."TEST00" failed -Column used in a PRIMARY constraint must be NOT NULL. - + INFO_00 After try to drop NN on FIELD, NN was added by ALTER SET NOT NULL + Table: PUBLIC.TEST00 + X INTEGER Not Null + CONSTRAINT T_PK: + Primary key (X) Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -ALTER TABLE TEST01 failed + -ALTER TABLE "PUBLIC"."TEST01" failed -Column used in a PRIMARY constraint must be NOT NULL. - + INFO_01 After try to drop NN on FIELD, NN was added directly in CREATE TABLE ( not null) + Table: PUBLIC.TEST01 + X (PUBLIC.DM_01) INTEGER Not Null + CONSTRAINT TEST01_PK: + Primary key (X) + INFO_02 After try to drop NN on FIELD, NN was inherited from DOMAIN + Table: PUBLIC.TEST02 + X (PUBLIC.DM_02) INTEGER Not Null + CONSTRAINT TEST02_PK: + Primary key (X) Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -ALTER DOMAIN DM_03 failed - -Domain used in the PRIMARY KEY constraint of table TEST03 must be NOT NULL - + -ALTER DOMAIN "PUBLIC"."DM_03" failed + -Domain used in the PRIMARY KEY constraint of table "PUBLIC"."TEST03" must be NOT NULL + INFO_03 After try to drop NN on DOMAIN but dependent table exists + PUBLIC.DM_03 INTEGER Not Null + Table: PUBLIC.TEST03 + X (PUBLIC.DM_03) INTEGER Not Null + CONSTRAINT TEST03_PK: + Primary key (X) + INFO_04 After try to drop NN on FIELD based on not-null domain, but NN was also specified in the field DDL + Table: PUBLIC.TEST04 + X (PUBLIC.DM_04) INTEGER Not Null + CONSTRAINT TEST04_PK: + Primary key (X) Statement failed, SQLSTATE = 22006 unsuccessful metadata update - -Cannot make field X of table TEST05 NOT NULL because there are NULLs present - + -Cannot make field "X" of table "PUBLIC"."TEST05" NOT NULL because there are NULLs present + INFO_05 After try to set NN on DOMAIN when at least one table exists with NULL in its data + PUBLIC.DM_05 INTEGER Nullable + INFO_06 After try to set NN on DOMAIN when NO table exists with NULL in its data + PUBLIC.DM_06 INTEGER Not Null Statement failed, SQLSTATE = 23000 - validation error for column "TEST06"."X", value "*** null ***" + validation error for column "PUBLIC"."TEST06"."X", value "*** null ***" """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_5x if act.is_version('<6') else expected_stderr_6x - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 671bc9b8c15fc686135ca67e388c893aa5038bd1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:51:46 +0300 Subject: [PATCH 0867/1064] Added/Updated tests\bugs\core_4733_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4733_test.py | 54 +++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_4733_test.py b/tests/bugs/core_4733_test.py index e9def6c2..d92eb548 100644 --- a/tests/bugs/core_4733_test.py +++ b/tests/bugs/core_4733_test.py @@ -9,6 +9,12 @@ DESCRIPTION: JIRA: CORE-4733 FBTEST: bugs.core_4733 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -64,40 +70,56 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 22006 + unsuccessful metadata update + -Cannot make field NUM of table TEST NOT NULL because there are NULLs present + -Cannot make field DTS of table TEST NOT NULL because there are NULLs present + -Cannot make field STR of table TEST NOT NULL because there are NULLs present + -Cannot make field BOO of table TEST NOT NULL because there are NULLs present NUM INTEGER Nullable DTS TIMESTAMP Nullable STR VARCHAR(10) CHARACTER SET UTF8 Nullable BOO BOOLEAN Nullable - NUM DTS STR BOO - - + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."NUM", value "*** null ***" NUM (DM_NN_INT) INTEGER Not Null DTS (DM_NN_DTS) TIMESTAMP Not Null STR (DM_NN_UTF) VARCHAR(10) CHARACTER SET UTF8 Not Null BOO (DM_NN_BOO) BOOLEAN Not Null """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 22006 unsuccessful metadata update - -Cannot make field NUM of table TEST NOT NULL because there are NULLs present - -Cannot make field DTS of table TEST NOT NULL because there are NULLs present - -Cannot make field STR of table TEST NOT NULL because there are NULLs present - -Cannot make field BOO of table TEST NOT NULL because there are NULLs present + -Cannot make field "NUM" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + -Cannot make field "DTS" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + -Cannot make field "STR" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + -Cannot make field "BOO" of table "PUBLIC"."TEST" NOT NULL because there are NULLs present + Table: PUBLIC.TEST + NUM INTEGER Nullable + DTS TIMESTAMP Nullable + STR VARCHAR(10) CHARACTER SET SYSTEM.UTF8 Nullable + BOO BOOLEAN Nullable + NUM + DTS + STR + BOO Statement failed, SQLSTATE = 23000 - validation error for column "TEST"."NUM", value "*** null ***" + validation error for column "PUBLIC"."TEST"."NUM", value "*** null ***" + Table: PUBLIC.TEST + NUM (PUBLIC.DM_NN_INT) INTEGER Not Null + DTS (PUBLIC.DM_NN_DTS) TIMESTAMP Not Null + STR (PUBLIC.DM_NN_UTF) VARCHAR(10) CHARACTER SET SYSTEM.UTF8 Not Null + BOO (PUBLIC.DM_NN_BOO) BOOLEAN Not Null """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1578b02fb37a84b0d6ceca05aa763cdcd45ff62e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 14:54:29 +0300 Subject: [PATCH 0868/1064] Added/Updated tests\bugs\core_4735_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4735_test.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_4735_test.py b/tests/bugs/core_4735_test.py index e4bbc1c4..8d224744 100644 --- a/tests/bugs/core_4735_test.py +++ b/tests/bugs/core_4735_test.py @@ -3,15 +3,20 @@ """ ID: issue-5041 ISSUE: 5041 -TITLE: Expression 'where bool_field IS true | false' should also use index as - 'where bool_field = true | false' (if such index exists) +TITLE: Expression 'where bool_field IS true | false' should also use index as 'where bool_field = true | false' (if such index exists) DESCRIPTION: -NOTES: -[28.01.2019] - Changed expected PLAN of execution after dimitr's letter 28.01.2019 17:28: - 'is NOT ' and 'is distinct from ' should use PLAN NATURAL. JIRA: CORE-4735 FBTEST: bugs.core_4735 +NOTES: + [28.01.2019] pzotov + Changed expected PLAN of execution after dimitr's letter 28.01.2019 17:28: + 'is NOT ' and 'is distinct from ' should use PLAN NATURAL. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -36,7 +41,7 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST INDEX (TEST_X)) PLAN (TEST INDEX (TEST_X)) PLAN (TEST INDEX (TEST_X)) @@ -47,9 +52,19 @@ PLAN (TEST NATURAL) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X")) + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST" NATURAL) + PLAN ("PUBLIC"."TEST" NATURAL) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From fb73639f6e1d81b341ada3830a824820626b3f23 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 15:56:26 +0300 Subject: [PATCH 0869/1064] Added/Updated tests\bugs\core_4738_test.py: Replaced 'SHOW TABLE' command with qery to RDB tables that displays field_type and field_length instead. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4738_test.py | 54 ++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4738_test.py b/tests/bugs/core_4738_test.py index fa49c324..5b30cda7 100644 --- a/tests/bugs/core_4738_test.py +++ b/tests/bugs/core_4738_test.py @@ -3,11 +3,18 @@ """ ID: issue-5043 ISSUE: 5043 -TITLE: Command "Alter table alter type " does not work: - "BLR syntax error: expected valid BLR code at offset 15, encountered 255" +TITLE: Command "Alter table alter type " does not work: "BLR syntax error: expected valid BLR code ..." DESCRIPTION: JIRA: CORE-4738 FBTEST: bugs.core_4738 +NOTES: + [30.06.2025] pzotov + This issue caused by regression when core-4733 ( https://github.com/FirebirdSQL/firebird/issues/5039 ) was fixed. + Commit for core-4733 (to check regression): http://sourceforge.net/p/firebird/code/61241 2015-04-05 02:24:40 +0000 + Confirmed bug on 3.0.0.31771. + + Replaced 'SHOW TABLE' command with qery to RDB tables that displays field_type and field_length instead. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,27 +23,56 @@ db = db_factory() test_script = """ - create domain dm_id int; + set list on; + create domain dm_id bigint; + commit; + + create table test(num smallint); commit; - create table test(num int); + create view v_info as + select + rf.rdb$field_name fld_name + ,f.rdb$field_type fld_type + ,f.rdb$field_length fld_length + ,f.rdb$field_scale fld_scale + from rdb$relation_fields rf + left join rdb$fields f on rf.rdb$field_source = f.rdb$field_name + where rf.rdb$relation_name = 'TEST'; commit; + select 'point-1' msg, v.* from v_info v; + alter table test alter num type dm_id; commit; - show table test; + select 'point-2' msg, v.* from v_info v; + + insert into test(num) values(-2147483648); + select * from test; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - NUM (DM_ID) INTEGER Nullable + MSG point-1 + FLD_NAME NUM + FLD_TYPE 7 + FLD_LENGTH 2 + FLD_SCALE 0 + + MSG point-2 + FLD_NAME NUM + FLD_TYPE 16 + FLD_LENGTH 8 + FLD_SCALE 0 + + NUM -2147483648 """ @pytest.mark.version('>=3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 840303cee00cf86f1f495b7e16551093d842c3e9 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:01:46 +0300 Subject: [PATCH 0870/1064] Added/Updated tests\bugs\core_4744_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4744_test.py | 69 +++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_4744_test.py b/tests/bugs/core_4744_test.py index 0b40461d..7c3cce69 100644 --- a/tests/bugs/core_4744_test.py +++ b/tests/bugs/core_4744_test.py @@ -3,11 +3,16 @@ """ ID: issue-5049 ISSUE: 5049 -TITLE: ALTER DATABASE SET DEFAULT CHARACTER SET: 1) take effect only for once for - current attachment; 2) does not check that new char set exists untill it will be used +TITLE: ALTER DATABASE SET DEFAULT CHARACTER SET: 1) take effect only for once for current attachment; 2) does not check that new char set exists untill it will be used DESCRIPTION: JIRA: CORE-4744 FBTEST: bugs.core_4744 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,7 +23,7 @@ test_script = """ set list on; - select rdb$character_set_name from rdb$database; + select rdb$character_set_name as db_char_set from rdb$database; commit; @@ -75,8 +80,9 @@ act = isql_act('db', test_script) -expected_stdout = """ - RDB$CHARACTER_SET_NAME UTF8 + +expected_stdout_5x = """ + DB_CHAR_SET UTF8 TAB_NAME TAB_850 FLD_NAME TXT_850 @@ -93,32 +99,63 @@ FLD_CSET WIN1252 DB_DEFAULT_CSET WIN1252 + Statement failed, SQLSTATE = 2C000 + unsuccessful metadata update + -ALTER DATABASE failed + -CHARACTER SET FOO_BAR_8859_4 is not defined + + Statement failed, SQLSTATE = HY004 + unsuccessful metadata update + -CREATE TABLE TAB_BAR failed + -Dynamic SQL Error + -SQL error code = -204 + -Data type unknown + -CHARACTER SET FOO_BAR_8859_4 is not defined + TAB_NAME TAB_FOO FLD_NAME TXT_8859_4 FLD_CSET WIN1252 DB_DEFAULT_CSET WIN1252 """ -expected_stderr = """ +expected_stdout_6x = """ + DB_CHAR_SET UTF8 + + TAB_NAME TAB_850 + FLD_NAME TXT_850 + FLD_CSET DOS850 + DB_DEFAULT_CSET DOS850 + + TAB_NAME TAB_866 + FLD_NAME TXT_866 + FLD_CSET DOS866 + DB_DEFAULT_CSET DOS866 + + TAB_NAME TAB_1252 + FLD_NAME TXT_1252 + FLD_CSET WIN1252 + DB_DEFAULT_CSET WIN1252 + Statement failed, SQLSTATE = 2C000 unsuccessful metadata update -ALTER DATABASE failed - -CHARACTER SET FOO_BAR_8859_4 is not defined - + -CHARACTER SET "PUBLIC"."FOO_BAR_8859_4" is not defined Statement failed, SQLSTATE = HY004 unsuccessful metadata update - -CREATE TABLE TAB_BAR failed + -CREATE TABLE "PUBLIC"."TAB_BAR" failed -Dynamic SQL Error -SQL error code = -204 -Data type unknown - -CHARACTER SET FOO_BAR_8859_4 is not defined + -CHARACTER SET "PUBLIC"."FOO_BAR_8859_4" is not defined + + TAB_NAME TAB_FOO + FLD_NAME TXT_8859_4 + FLD_CSET WIN1252 + DB_DEFAULT_CSET WIN1252 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 02f9b521ab3790441af857c60901d84e64ec7c2e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:05:17 +0300 Subject: [PATCH 0871/1064] Added/Updated tests\bugs\core_4754_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4754_test.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4754_test.py b/tests/bugs/core_4754_test.py index 4b066059..16b69722 100644 --- a/tests/bugs/core_4754_test.py +++ b/tests/bugs/core_4754_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4754 FBTEST: bugs.core_4754 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -23,11 +29,18 @@ act = python_act('db') -expected_stdout = """ -Error-1: -lock conflict on no wait transaction --unsuccessful metadata update --object TABLE "GTT_SESSION" is in use +expected_stdout_5x = """ + Error-1: + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "GTT_SESSION" is in use +""" + +expected_stdout_6x = """ + Error-1: + lock conflict on no wait transaction + -unsuccessful metadata update + -object TABLE "PUBLIC"."GTT_SESSION" is in use """ @pytest.mark.version('>=3') @@ -60,6 +73,6 @@ def test_1(act: Action, capsys): print('Error-2:') print(e.args[0]) # - act.expected_stdout = expected_stdout + 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 From 3dcc42cc1ff5a187c14e370eb6ded625077ddde2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:07:48 +0300 Subject: [PATCH 0872/1064] Added/Updated tests\bugs\core_4755_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4755_test.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_4755_test.py b/tests/bugs/core_4755_test.py index 962009da..d093a467 100644 --- a/tests/bugs/core_4755_test.py +++ b/tests/bugs/core_4755_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4755 FBTEST: bugs.core_4755 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -80,19 +86,28 @@ act = isql_act('db', test_script, substitutions=[('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 exception 1 -EX_SOMETHING_WRONG -Arguments for raising exeption: 10001 10002 10003 10004 10005 10006 10007 10008 10009 - -At block line: 12, col: 5 + -At block line + Statement failed, SQLSTATE = 07002 + Number of arguments (10) exceeds the maximum (9) number of EXCEPTION USING arguments +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -"PUBLIC"."EX_SOMETHING_WRONG" + -Arguments for raising exeption: 10001 10002 10003 10004 10005 10006 10007 10008 10009 + -At block line Statement failed, SQLSTATE = 07002 Number of arguments (10) exceeds the maximum (9) number of EXCEPTION USING arguments """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From aa0bcd1095875d6430631744b7e68b3acd4adb8b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:19:59 +0300 Subject: [PATCH 0873/1064] Added/Updated tests\bugs\core_4766_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4766_test.py | 102 ++++++++++++++--------------------- 1 file changed, 40 insertions(+), 62 deletions(-) diff --git a/tests/bugs/core_4766_test.py b/tests/bugs/core_4766_test.py index 6e444029..c21e726c 100644 --- a/tests/bugs/core_4766_test.py +++ b/tests/bugs/core_4766_test.py @@ -3,19 +3,22 @@ """ ID: issue-5066 ISSUE: 5066 -TITLE: AV when trying to manage users list using EXECUTE STATEMENT on behalf of - non-sysdba user which has RDB$ADMIN role +TITLE: AV when trying to manage users list using EXECUTE STATEMENT on behalf of non-sysdba user which has RDB$ADMIN role DESCRIPTION: -NOTES: -[24.11.2021] pcisar - On FB v4.0.0.2496 this test fails as provided script file 'core_4766.sql' raises error in - execute block->execute statement->create/drop user: - Statement failed, SQLSTATE = 28000 - Your user name and password are not defined. Ask your database administrator to set up a Firebird login. - -At block line: 3, col: 9 - Variant for FB 3 works fine. JIRA: CORE-4766 FBTEST: bugs.core_4766 +NOTES: + [24.11.2021] pcisar + On FB v4.0.0.2496 this test fails as provided script file 'core_4766.sql' raises error in + execute block->execute statement->create/drop user: + Statement failed, SQLSTATE = 28000 / Your user name and password are not defined... + Variant for FB 3 works fine. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -26,82 +29,56 @@ act = python_act('db', substitutions=[('TCPv.*', 'TCP'), ('.*After line \\d+.*', ''), ('find/delete', 'delete'), ('TABLE PLG\\$.*', 'TABLE PLG')]) -# version: 3.0 - -expected_stdout_1 = """ - Srp: BOSS_SEC_NAME TMP_4766_BOSS - Srp: BOSS_SEC_PLUGIN Srp - Srp: BOSS_SEC_IS_ADMIN - Srp: Statement failed, SQLSTATE = 28000 - Srp: add record error - Srp: -no permission for INSERT access to TABLE PLG$SRP_VIEW - - Srp: MNGR_SEC_NAME - Srp: MNGR_SEC_PLUGIN - Srp: MNGR_SEC_IS_ADMIN - Srp: Statement failed, SQLSTATE = 28000 - Srp: delete record error - Srp: -no permission for DELETE access to TABLE PLG$SRP_VIEW - - +expected_stdout_3x = """ Leg: BOSS_SEC_NAME TMP_4766_BOSS Leg: BOSS_SEC_PLUGIN Legacy_UserManager Leg: BOSS_SEC_IS_ADMIN Leg: Statement failed, SQLSTATE = 28000 Leg: add record error - Leg: -no permission for INSERT access to TABLE PLG$VIEW_USERS - + Leg: -no permission for INSERT access to TABLE PLG Leg: MNGR_SEC_NAME Leg: MNGR_SEC_PLUGIN Leg: MNGR_SEC_IS_ADMIN - Leg: Statement failed, SQLSTATE = 28000 - Leg: find/delete record error - Leg: -no permission for DELETE access to TABLE PLG$VIEW_USERS - + Leg: delete record error + Leg: -no permission for DELETE access to TABLE PLG """ -@pytest.mark.version('>=3.0,<4') -def test_1(act: Action, capsys): - sql_text = (act.files_dir / 'core_4766.sql').read_text() - subs = {'dsn': act.db.dsn, 'user_name': act.db.user, 'user_password': act.db.password, - 'current_auth_plugin': None,} - for current_auth_plugin in ['Srp', 'Legacy_UserManager']: - subs['current_auth_plugin'] = current_auth_plugin - act.reset() - act.isql(switches=['-q'], input=sql_text % subs, combine_output=True) - for line in act.clean_stdout.splitlines(): - if line.strip(): - print(current_auth_plugin[:3] + ': ' + line) - # - act.reset() - act.expected_stdout = expected_stdout_1 - act.stdout = capsys.readouterr().out - assert act.clean_stdout == act.clean_expected_stdout - -# version: 4.0 - -expected_stdout_2 = """ +expected_stdout_5x = """ Leg: BOSS_SEC_NAME TMP_4766_BOSS Leg: BOSS_SEC_PLUGIN Legacy_UserManager Leg: BOSS_SEC_IS_ADMIN - Leg: Statement failed, SQLSTATE = 28000 Leg: add record error - Leg: -no permission for INSERT access to TABLE PLG$VIEW_USERS + Leg: -no permission for INSERT access to TABLE PLG Leg: -Effective user is TMP_4766_BOSS - Leg: MNGR_SEC_NAME Leg: MNGR_SEC_PLUGIN Leg: MNGR_SEC_IS_ADMIN + Leg: Statement failed, SQLSTATE = 28000 + Leg: delete record error + Leg: -no permission for DELETE access to TABLE PLG + Leg: -Effective user is TMP_4766_BOSS +""" +expected_stdout_6x = """ + Leg: BOSS_SEC_NAME TMP_4766_BOSS + Leg: BOSS_SEC_PLUGIN Legacy_UserManager + Leg: BOSS_SEC_IS_ADMIN + Leg: Statement failed, SQLSTATE = 28000 + Leg: add record error + Leg: -no permission for INSERT access to TABLE "PLG$LEGACY_SEC"."PLG$VIEW_USERS" + Leg: -Effective user is TMP_4766_BOSS + Leg: MNGR_SEC_NAME + Leg: MNGR_SEC_PLUGIN + Leg: MNGR_SEC_IS_ADMIN Leg: Statement failed, SQLSTATE = 28000 - Leg: find/delete record error - Leg: -no permission for DELETE access to TABLE PLG$VIEW_USERS + Leg: delete record error + Leg: -no permission for DELETE access to TABLE "PLG$LEGACY_SEC"."PLG$VIEW_USERS" Leg: -Effective user is TMP_4766_BOSS """ -@pytest.mark.version('>=4.0') +@pytest.mark.version('>=3.0') def test_2(act: Action, capsys): sql_text = (act.files_dir / 'core_4766.sql').read_text() # ::: NB ::: @@ -119,6 +96,7 @@ def test_2(act: Action, capsys): print(current_auth_plugin[:3] + ': ' + line) # act.reset() - act.expected_stdout = expected_stdout_2 + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else 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 From 0c9c277efdcb777f059258c3ba6890ea65d4166e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:29:26 +0300 Subject: [PATCH 0874/1064] Added/Updated tests\bugs\core_4774_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4774_test.py | 50 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_4774_test.py b/tests/bugs/core_4774_test.py index 0623e970..9e862177 100644 --- a/tests/bugs/core_4774_test.py +++ b/tests/bugs/core_4774_test.py @@ -5,13 +5,19 @@ ISSUE: 5073 TITLE: Table aliasing is unnecessary required when doing UPDATE ... RETURNING RDB$ pseudo-columns DESCRIPTION: -NOTES: - After fix #6815 execution plan contains 'Local_Table' (FB 5.0+) for DML with RETURNING clauses: - "When such a statement is executed, Firebird should execute the statement to completion - and collect all requested data in a type of temporary table, once execution is complete, - fetches are done against this temporary table" JIRA: CORE-4774 FBTEST: bugs.core_4774 +NOTES: + After fix #6815 execution plan contains 'Local_Table' (FB 5.0+) for DML with RETURNING clauses: + "When such a statement is executed, Firebird should execute the statement to completion + and collect all requested data in a type of temporary table, once execution is complete, + fetches are done against this temporary table" + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -33,36 +39,32 @@ act = isql_act('db', test_script) -# version: 3.0 - -expected_stdout_1 = """ +expected_stdout_4x = """ PLAN (T NATURAL) PLAN (T NATURAL) PLAN (T NATURAL) """ -@pytest.mark.version('>=3.0,<5.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout_1 - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - -# version: 5.0 - -expected_stdout_2 = """ +expected_stdout_5x = """ PLAN (T NATURAL) PLAN (Local_Table NATURAL) - PLAN (T NATURAL) PLAN (Local_Table NATURAL) - PLAN (T NATURAL) PLAN (Local_Table NATURAL) """ -@pytest.mark.version('>=5.0') -def test_2(act: Action): - act.expected_stdout = expected_stdout_2 - act.execute() - assert act.clean_stdout == act.clean_expected_stdout +expected_stdout_6x = """ + PLAN ("PUBLIC"."T" NATURAL) + PLAN (Local_Table NATURAL) + PLAN ("PUBLIC"."T" NATURAL) + PLAN (Local_Table NATURAL) + PLAN ("PUBLIC"."T" NATURAL) + PLAN (Local_Table NATURAL) +""" +@pytest.mark.version('>=3.0') +def test(act: Action): + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 6558c79415ca933aba39c986a5d9cff045b40102 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:51:45 +0300 Subject: [PATCH 0875/1064] Added/Updated tests\bugs\core_4782_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4782_test.py | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_4782_test.py b/tests/bugs/core_4782_test.py index b201a6a6..ba480af3 100644 --- a/tests/bugs/core_4782_test.py +++ b/tests/bugs/core_4782_test.py @@ -2,11 +2,22 @@ """ ID: issue-5081 -ISSUE: 5081 -TITLE: Command `SHOW TABLE` fails when the table contains field with unicode collationin its DDL +ISSUE: https://github.com/FirebirdSQL/firebird/issues/5081 +TITLE: Command `SHOW TABLE` fails when the table contains field with unicode collation in its DDL DESCRIPTION: JIRA: CORE-4782 FBTEST: bugs.core_4782 +NOTES: + [30.06.2025] pzotov + 1. Regression was fixed in http://sourceforge.net/p/firebird/code/61521 2015-05-11 15:48:35 +0000 + Confirmed bug on 3.0.0.31828, got: + Statement failed, SQLSTATE = 22001 + arithmetic exception, numeric overflow, or string truncation + -string right truncation + -expected length 7, actual 9 + 2. Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,25 +25,30 @@ db = db_factory(charset='UTF8') -test_script = """ +TABLE_DDL = 'create table "ĄČĘĢÆĖŠŚÖÜØ£"("ąčęėįšųūž" varchar(100) character set utf8 collate test_coll)' +test_script = f""" -- NB: it was connection charset = UTF8 that causes error, title of ticket should be changed. - create view v_test as select d.rdb$relation_id from rdb$database d; + create collation test_coll for utf8 from unicode; commit; - show view v_test; + {TABLE_DDL}; + commit; + show table "ĄČĘĢÆĖŠŚÖÜØ£"; """ act = isql_act('db', test_script, substitutions=[('=.*', '')]) -expected_stdout = """ - RDB$RELATION_ID (RDB$RELATION_ID) SMALLINT Nullable - View Source: - ==== ====== - select d.rdb$relation_id from rdb$database d +expected_stdout_5x = """ + ąčęėįšųūž VARCHAR(100) CHARACTER SET UTF8 Nullable + COLLATE TEST_COLL +""" + +expected_stdout_6x = """ + Table: PUBLIC."ĄČĘĢÆĖŠŚÖÜØ£" + "ąčęėįšųūž" VARCHAR(100) CHARACTER SET SYSTEM.UTF8 COLLATE PUBLIC.TEST_COLL Nullable """ @pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() +def test(act: Action): + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From d8e4e66681acc844b23a097cf25873f25e1dccfb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:53:46 +0300 Subject: [PATCH 0876/1064] Added/Updated tests\bugs\core_4782_test.py: added marker --- tests/bugs/core_4782_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bugs/core_4782_test.py b/tests/bugs/core_4782_test.py index ba480af3..0eff0136 100644 --- a/tests/bugs/core_4782_test.py +++ b/tests/bugs/core_4782_test.py @@ -47,6 +47,7 @@ "ąčęėįšųūž" VARCHAR(100) CHARACTER SET SYSTEM.UTF8 COLLATE PUBLIC.TEST_COLL Nullable """ +@pytest.mark.intl @pytest.mark.version('>=3.0') def test(act: Action): act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 64516dda7028c4201ba7808faee856f6c3845116 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 16:58:06 +0300 Subject: [PATCH 0877/1064] Added/Updated tests\bugs\core_4786_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4786_test.py | 142 ++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/tests/bugs/core_4786_test.py b/tests/bugs/core_4786_test.py index 6bb48c9d..3667a90e 100644 --- a/tests/bugs/core_4786_test.py +++ b/tests/bugs/core_4786_test.py @@ -3,11 +3,14 @@ """ ID: issue-5085 ISSUE: 5085 -TITLE: Problematic key value (when attempt to insert duplicate in PK/UK) is not shown - where length of key >= 127 characters +TITLE: Problematic key value (when attempt to insert duplicate in PK/UK) is not shown where length of key >= 127 characters DESCRIPTION: JIRA: CORE-4786 FBTEST: bugs.core_4786 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -68,71 +71,74 @@ act = isql_act('db', test_script) -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_NONE_UNQ" on table "TEST_NONE" - -Problematic key value is ("S" = '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234ABCD...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDEF') - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁ...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊ...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = '€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = '∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁ...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑Á...) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table "TEST_UTF8" - -Problematic key value is ("S" = 'Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑...) -""" - +@pytest.mark.intl @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute(charset='utf8') - assert act.clean_stderr == act.clean_expected_stderr - + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_NONE_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_NONE" + -Problematic key value is ("S" = '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234ABCD...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDEF') + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁ...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊЊ...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = '€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = '∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á∑Á...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ∑ÁÁ...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ∑ÁÁÁ...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑∑ÁÁÁ∑...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁÁ∑ÁÁÁ...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑Á∑∑...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑∑∑Á∑...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑ÁÁ∑∑∑Á...) + + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_CSET_UTF8_UNQ" on table {SQL_SCHEMA_PREFIX}"TEST_UTF8" + -Problematic key value is ("S" = 'Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑∑Á∑∑∑...) + """ + + act.expected_stdout = expected_stdout + act.execute(charset='utf8', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 3405ac9e6f1ecf404ec72dfe03e50ccc1ff3a86b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 18:44:06 +0300 Subject: [PATCH 0878/1064] Added/Updated tests\bugs\core_4806_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4806_test.py | 93 +++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_4806_test.py b/tests/bugs/core_4806_test.py index 720c06a0..21dca760 100644 --- a/tests/bugs/core_4806_test.py +++ b/tests/bugs/core_4806_test.py @@ -30,6 +30,12 @@ [15.05.2025] pzotov Removed 'show grants' because its output very 'fragile' and can often change in fresh FB versions. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -103,9 +109,9 @@ commit; """ -substitutions = [ ('[ \t]+', ' ') - ,('(-)?Effective user is.*', '') - ,('current value.*', 'current value') +substitutions = [ # ('[ \t]+', ' '), + # ('(-)?Effective user is.*', ''), + ('current value.*', 'current value') ] act = isql_act('db', test_script, substitutions = substitutions) @@ -113,33 +119,94 @@ @pytest.mark.version('>=3.0') def test_1(act: Action, user_a: User, user_b: User, user_c: User, role_a: Role): - act.expected_stdout = """ - USER BIG_BROTHER + # user_a = user_factory('db', name='Maverick', password='123') + # user_b = user_factory('db', name='Big_Brother', password='456') + # user_c = user_factory('db', name='Bill_Junior', password='789') + # role_a = role_factory('db', name='stockmgr') + + expected_stdout_3x = f""" + USER {user_b.name.upper()} + ROLE NONE + Generator G, current value + NEW_GEN -111 + USER {user_c.name.upper()} + ROLE {role_a.name.upper()} + Generator G, current value + NEW_GEN -333 + USER {user_c.name.upper()} + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + USER {user_a.name.upper()} + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR G + """ + + expected_stdout_5x = f""" + USER {user_b.name.upper()} ROLE NONE Generator G, current value: 0, initial value: 1, increment: 1 NEW_GEN -111 - USER BILL_JUNIOR - ROLE STOCKMGR + USER {user_c.name.upper()} + ROLE {role_a.name.upper()} Generator G, current value: -111, initial value: 1, increment: 1 NEW_GEN -333 - USER BILL_JUNIOR + USER {user_c.name.upper()} ROLE NONE Statement failed, SQLSTATE = 28000 no permission for USAGE access to GENERATOR G - -Effective user is BILL_JUNIOR + -Effective user is {user_c.name.upper()} There is no generator G in this database Statement failed, SQLSTATE = 28000 no permission for USAGE access to GENERATOR G - -Effective user is BILL_JUNIOR - USER MAVERICK + -Effective user is {user_c.name.upper()} + USER {user_a.name.upper()} ROLE NONE Statement failed, SQLSTATE = 28000 no permission for USAGE access to GENERATOR G - -Effective user is MAVERICK + -Effective user is {user_a.name.upper()} There is no generator G in this database Statement failed, SQLSTATE = 28000 no permission for USAGE access to GENERATOR G - -Effective user is MAVERICK + -Effective user is {user_a.name.upper()} """ + + expected_stdout_6x = f""" + USER {user_b.name.upper()} + ROLE NONE + Generator PUBLIC.G, current value + NEW_GEN -111 + USER {user_c.name.upper()} + ROLE {role_a.name.upper()} + Generator PUBLIC.G, current value + NEW_GEN -333 + USER {user_c.name.upper()} + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR "PUBLIC"."G" + -Effective user is {user_c.name.upper()} + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR "PUBLIC"."G" + -Effective user is {user_c.name.upper()} + USER {user_a.name.upper()} + ROLE NONE + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR "PUBLIC"."G" + -Effective user is {user_a.name.upper()} + There is no generator G in this database + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR "PUBLIC"."G" + -Effective user is {user_a.name.upper()} + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From edd3c28099662263545300c9fd5f6d1fa2a25f12 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 18:52:51 +0300 Subject: [PATCH 0879/1064] Added/Updated tests\bugs\core_4807_test.py: Removed check of STDOUT: no sense in this test. Only STDERR must be checked. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4807_test.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_4807_test.py b/tests/bugs/core_4807_test.py index 08df0577..465d1b07 100644 --- a/tests/bugs/core_4807_test.py +++ b/tests/bugs/core_4807_test.py @@ -5,10 +5,14 @@ ISSUE: 5105 TITLE: Regression: List of aggregation is not checked properly DESCRIPTION: - Field inside subquery not present in GROUP BY clause and therefore can't be used in - SELECT list as is (only as argument of some aggregation function). + Field inside subquery not present in GROUP BY clause and therefore can't be used in + SELECT list as is (only as argument of some aggregation function). JIRA: CORE-4807 FBTEST: bugs.core_4807 +NOTES: + [30.06.2025] pzotov + Removed check of STDOUT: no sense in this test. Only STDERR must be checked. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,11 +33,6 @@ act = isql_act('db', test_script, substitutions=[('SORT \\(\\(T NATURAL\\)\\)', 'SORT (T NATURAL)')]) -expected_stdout = """ - PLAN (RDB$DATABASE NATURAL) - PLAN SORT ((T NATURAL)) -""" - expected_stderr = """ Statement failed, SQLSTATE = 42000 Dynamic SQL Error @@ -41,11 +40,8 @@ -Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) """ -@pytest.mark.version('>=3') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.execute(combine_output = False) + assert act.clean_stderr == act.clean_expected_stderr From e0ca9a5397f1866ec68685556426aae871761081 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 19:17:22 +0300 Subject: [PATCH 0880/1064] Added/Updated tests\bugs\core_4809_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4809_test.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_4809_test.py b/tests/bugs/core_4809_test.py index 425e6c5e..94d96322 100644 --- a/tests/bugs/core_4809_test.py +++ b/tests/bugs/core_4809_test.py @@ -18,6 +18,12 @@ result of HASH(A, B) is considered now as having greater cardinality than HASH(C). This causes optimizer to put HASH(A,B) as first source. Checked on 5.0.0.1149. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -227,9 +233,30 @@ PLAN HASH (HASH (HASH (DATASOURCE_A TF NATURAL, DATASOURCE_B TF NATURAL), DATASOURCE_C TF NATURAL), DATASOURCE_D TF NATURAL) """ +fb6x_checked_stdout = """ + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL, "DATASOURCE_C" "PUBLIC"."TK" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL, "DATASOURCE_C" "PUBLIC"."TK" NATURAL, "DATASOURCE_D" "PUBLIC"."TK" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL) + PLAN HASH (HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL), "DATASOURCE_C" "PUBLIC"."TK" NATURAL) + PLAN HASH (HASH (HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL), "DATASOURCE_C" "PUBLIC"."TK" NATURAL), "DATASOURCE_D" "PUBLIC"."TK" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL) + PLAN HASH (HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL), "DATASOURCE_C" "PUBLIC"."TK" NATURAL) + PLAN HASH (HASH (HASH ("DATASOURCE_A" "PUBLIC"."TK" NATURAL, "DATASOURCE_B" "PUBLIC"."TK" NATURAL), "DATASOURCE_C" "PUBLIC"."TK" NATURAL), "DATASOURCE_D" "PUBLIC"."TK" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL, "DATASOURCE_C" "PUBLIC"."TF" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL, "DATASOURCE_C" "PUBLIC"."TF" NATURAL, "DATASOURCE_D" "PUBLIC"."TF" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL) + PLAN HASH (HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL), "DATASOURCE_C" "PUBLIC"."TF" NATURAL) + PLAN HASH (HASH (HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL), "DATASOURCE_C" "PUBLIC"."TF" NATURAL), "DATASOURCE_D" "PUBLIC"."TF" NATURAL) + PLAN HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL) + PLAN HASH (HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL), "DATASOURCE_C" "PUBLIC"."TF" NATURAL) + PLAN HASH (HASH (HASH ("DATASOURCE_A" "PUBLIC"."TF" NATURAL, "DATASOURCE_B" "PUBLIC"."TF" NATURAL), "DATASOURCE_C" "PUBLIC"."TF" NATURAL), "DATASOURCE_D" "PUBLIC"."TF" NATURAL) +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = fb3x_checked_stdout if act.is_version('<4') else fb4x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout + act.expected_stdout = fb3x_checked_stdout if act.is_version('<4') else fb4x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From a3657d52eaa4c7510fa6c8dd45a04e4e118a5ee2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 19:34:00 +0300 Subject: [PATCH 0881/1064] Added/Updated tests\bugs\core_4811_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4811_test.py | 323 +++++++++++++++++------------------ 1 file changed, 159 insertions(+), 164 deletions(-) diff --git a/tests/bugs/core_4811_test.py b/tests/bugs/core_4811_test.py index 2bbaf2d7..3c79cdb6 100644 --- a/tests/bugs/core_4811_test.py +++ b/tests/bugs/core_4811_test.py @@ -7,182 +7,177 @@ DESCRIPTION: JIRA: CORE-4811 FBTEST: bugs.core_4811 +NOTES: + [29.06.2025] pzotov + Re-implemented: use f-notation and variables to be substituted in the expected output. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('set echo.*', ''), ('Use CONNECT or CREATE DATABASE.*', ''), - ('Your user name and password.*', ''), ('line: [0-9]+, col: [0-9]+', ''), - ('exception [0-9]+', 'exception')] - db = db_factory() tmp_user = user_factory('db', name='tmp$c4811', password='1') tmp_role = role_factory('db', name='Boss') -test_script = """ - set wng off; - set list on; - create or alter procedure sp_check_actual_role as begin end; - commit; - - recreate exception ex_have_no_role 'You''ve specified role: >@1< -- but your actual role is NONE.'; - - set term ^; - create or alter procedure sp_check_actual_role( - a_probe_role varchar(31) - ) returns( - checking varchar(80), - result varchar(31) - ) as - begin - if ( upper(current_role) = 'NONE' ) - then - exception ex_have_no_role using ( a_probe_role ); - - checking = 'role: >' || a_probe_role || '< - ' - || trim( - iif( a_probe_role containing '''', 'in apostrophes', - iif( a_probe_role containing '"', 'in double quotes', 'without delimiters' ) - ) - ) - || ', ' || iif( upper(a_probe_role) = a_probe_role, 'UPPER case', 'CaMeL case' ) - ; - result = current_role; - suspend; - end - ^ - set term ;^ - commit; - - set bail on; - set echo on; - grant Boss to Tmp$c4811; - grant usage on exception ex_have_no_role to Tmp$c4811; - grant execute on procedure sp_check_actual_role to Tmp$c4811; - set echo off; - set bail off; - -- show grants; - commit; - - -- set echo on; - - -- checking for USER name: - - connect '$(DSN)' user 'Tmp$c4811' password '1'; - -- PASSES since http://sourceforge.net/p/firebird/code/62016 (2015-07-16 14:26), this was build = 31981 - select 'user: >''Tmp$c4811''< - in apostrophes, CaMeL case' checking, current_user as result from rdb$database; - commit; - - connect '$(DSN)' user 'TMP$C4811' password '1'; -- should PASS, checked on builds 31948, 31981 - select 'user: >''TMP$C4811''< - in apostrophes, UPPER case' checking, current_user as result from rdb$database; - commit; - - connect '$(DSN)' user Tmp$c4811 password '1'; -- should PASS, checked on builds 31948, 31981 - select 'user: >Tmp$c4811< - without delimiters, CaMeL case' checking, current_user as result from rdb$database; - commit; - - connect '$(DSN)' user TMP$C4811 password '1'; -- should PASS, checked on builds 31948, 31981 - select 'user: >TMP$C4811< - without delimiters, UPPER case' checking, current_user as result from rdb$database; - commit; - - connect '$(DSN)' user "Tmp$c4811" password '1'; -- should *** FAIL *** - select 'user: >"Tmp$c4811"< - in double quotes, CaMeL case' checking, current_user as result from rdb$database; - commit; - - connect '$(DSN)' user "TMP$C4811" password '1'; -- should PASS, checked on builds 31948, 31981 - select 'user: >"TMP$C4811" - in double quotes, UPPER case' checking, current_user as result from rdb$database; - commit; - - -- checking for ROLE (actual role in all following cases will be: [BOSS], checked on builds 31948, 31981) - - -- Statement that created role (see above): - -- create role Boss; - - -- Enclosing role in apostrophes and specifying it exactly like it was in its creation sttm: - connect '$(DSN)' user 'TMP$C4811' password '1' role 'Boss'; - select * from sp_check_actual_role( '''Boss''' ); --------------- should return: BOSS - commit; - - -- Enclosing role in apostrophes and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): - connect '$(DSN)' user 'TMP$C4811' password '1' role 'BOSS'; - select * from sp_check_actual_role( '''BOSS''' ); --------------- should return: BOSS - commit; - - -- do NOT enclosing role in any delimiters and change CaSe of its characters (i.e. differ than in its CREATE ROLE statement): - connect '$(DSN)' user 'TMP$C4811' password '1' role BosS; - select * from sp_check_actual_role( 'BosS' ); --------------- should return: BOSS - commit; - - -- do NOT enclosing role in any delimiters and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): - connect '$(DSN)' user 'TMP$C4811' password '1' role BOSS; - select * from sp_check_actual_role( 'BOSS' ); --------------- should return: BOSS - commit; - - -- Enclosing role in double quotes and change CaSe of its characters (i.e. differ than in its CREATE ROLE statement): - connect '$(DSN)' user 'TMP$C4811' password '1' role "BoSs"; - select * from sp_check_actual_role( '"BoSs"' ); --------------- should raise EX_HAVE_NO_ROLE, actual role will be 'NONE' - commit; - - -- Enclosing role in double quotes and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): - connect '$(DSN)' user 'TMP$C4811' password '1' role "BOSS"; - select * from sp_check_actual_role( '"BOSS"' ); --------------- should return: BOSS - commit; -""" - -act = isql_act('db', test_script, substitutions=substitutions) - -expected_stdout = """ - grant Boss to Tmp$c4811; - grant usage on exception ex_have_no_role to Tmp$c4811; - grant execute on procedure sp_check_actual_role to Tmp$c4811; - - CHECKING user: >'Tmp$c4811'< - in apostrophes, CaMeL case - RESULT TMP$C4811 - - CHECKING user: >'TMP$C4811'< - in apostrophes, UPPER case - RESULT TMP$C4811 - - CHECKING user: >Tmp$c4811< - without delimiters, CaMeL case - RESULT TMP$C4811 - - CHECKING user: >TMP$C4811< - without delimiters, UPPER case - RESULT TMP$C4811 - - CHECKING user: >"TMP$C4811" - in double quotes, UPPER case - RESULT TMP$C4811 +substitutions = [('set echo.*', ''), ('[ \t]+', ' '), ('exception \\d+', 'exception'), ('line(:)?\\s+\\d+.*', '')] +act = isql_act('db', substitutions = substitutions) - CHECKING role: >'Boss'< - in apostrophes, CaMeL case - RESULT BOSS - - CHECKING role: >'BOSS'< - in apostrophes, UPPER case - RESULT BOSS - - CHECKING role: >BosS< - without delimiters, CaMeL case - RESULT BOSS - - CHECKING role: >BOSS< - without delimiters, UPPER case - RESULT BOSS - - CHECKING role: >"BOSS"< - in double quotes, UPPER case - RESULT BOSS -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - Statement failed, SQLSTATE = HY000 - exception 3 - -EX_HAVE_NO_ROLE - -You've specified role: >"BoSs"< -- but your actual role is NONE. - -At procedure 'SP_CHECK_ACTUAL_ROLE' -""" @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User, tmp_role: Role): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + test_script = f""" + set wng off; + set list on; + create or alter procedure sp_check_actual_role as begin end; + commit; + + recreate exception ex_have_no_role 'You''ve specified role: >@1< -- but your actual role is NONE.'; + + set term ^; + create or alter procedure sp_check_actual_role( + a_probe_role varchar(31) + ) returns( + checking varchar(80), + result varchar(31) + ) as + begin + if ( upper(current_role) = 'NONE' ) + then + exception ex_have_no_role using ( a_probe_role ); + + checking = 'role: >' || a_probe_role || '< - ' + || trim( + iif( a_probe_role containing '''', 'in apostrophes', + iif( a_probe_role containing '"', 'in double quotes', 'without delimiters' ) + ) + ) + || ', ' || iif( upper(a_probe_role) = a_probe_role, 'UPPER case', 'CaMeL case' ) + ; + result = current_role; + suspend; + end + ^ + set term ;^ + commit; + + set bail on; + set echo on; + grant Boss to Tmp$c4811; + grant usage on exception ex_have_no_role to Tmp$c4811; + grant execute on procedure sp_check_actual_role to Tmp$c4811; + set echo off; + set bail off; + -- show grants; + commit; + + -- set echo on; + + -- checking for USER name: + + connect '{act.db.dsn}' user 'Tmp$c4811' password '1'; + -- PASSES since http://sourceforge.net/p/firebird/code/62016 (2015-07-16 14:26), this was build = 31981 + select 'user: >''Tmp$c4811''< - in apostrophes, CaMeL case' checking, current_user as result from rdb$database; + commit; + + connect '{act.db.dsn}' user 'TMP$C4811' password '1'; -- should PASS, checked on builds 31948, 31981 + select 'user: >''TMP$C4811''< - in apostrophes, UPPER case' checking, current_user as result from rdb$database; + commit; + + connect '{act.db.dsn}' user Tmp$c4811 password '1'; -- should PASS, checked on builds 31948, 31981 + select 'user: >Tmp$c4811< - without delimiters, CaMeL case' checking, current_user as result from rdb$database; + commit; + + connect '{act.db.dsn}' user TMP$C4811 password '1'; -- should PASS, checked on builds 31948, 31981 + select 'user: >TMP$C4811< - without delimiters, UPPER case' checking, current_user as result from rdb$database; + commit; + + connect '{act.db.dsn}' user "Tmp$c4811" password '1'; -- should *** FAIL *** + select 'user: >"Tmp$c4811"< - in double quotes, CaMeL case' checking, current_user as result from rdb$database; + commit; + + connect '{act.db.dsn}' user "TMP$C4811" password '1'; -- should PASS, checked on builds 31948, 31981 + select 'user: >"TMP$C4811" - in double quotes, UPPER case' checking, current_user as result from rdb$database; + commit; + + -- checking for ROLE (actual role in all following cases will be: [BOSS], checked on builds 31948, 31981) + + -- Statement that created role (see above): + -- create role Boss; + + -- Enclosing role in apostrophes and specifying it exactly like it was in its creation sttm: + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role 'Boss'; + select * from sp_check_actual_role( '''Boss''' ); --------------- should return: BOSS + commit; + + -- Enclosing role in apostrophes and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role 'BOSS'; + select * from sp_check_actual_role( '''BOSS''' ); --------------- should return: BOSS + commit; + + -- do NOT enclosing role in any delimiters and change CaSe of its characters (i.e. differ than in its CREATE ROLE statement): + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role BosS; + select * from sp_check_actual_role( 'BosS' ); --------------- should return: BOSS + commit; + + -- do NOT enclosing role in any delimiters and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role BOSS; + select * from sp_check_actual_role( 'BOSS' ); --------------- should return: BOSS + commit; + + -- Enclosing role in double quotes and change CaSe of its characters (i.e. differ than in its CREATE ROLE statement): + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role "BoSs"; + select * from sp_check_actual_role( '"BoSs"' ); --------------- should raise EX_HAVE_NO_ROLE, actual role will be 'NONE' + commit; + + -- Enclosing role in double quotes and specifying it in UPPERCASE (i.e. differ than in its CREATE ROLE statement): + connect '{act.db.dsn}' user 'TMP$C4811' password '1' role "BOSS"; + select * from sp_check_actual_role( '"BOSS"' ); --------------- should return: BOSS + commit; + """ + + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + EXCEPTION_NAME = "EX_HAVE_NO_ROLE" if act.is_version('<6') else '"EX_HAVE_NO_ROLE"' + STORED_PROC_NAME = "'SP_CHECK_ACTUAL_ROLE'" if act.is_version('<6') else '"SP_CHECK_ACTUAL_ROLE"' + expected_stdout = f""" + grant Boss to Tmp$c4811; + grant usage on exception ex_have_no_role to Tmp$c4811; + grant execute on procedure sp_check_actual_role to Tmp$c4811; + CHECKING user: >'Tmp$c4811'< - in apostrophes, CaMeL case + RESULT {tmp_user.name.upper()} + CHECKING user: >'TMP$C4811'< - in apostrophes, UPPER case + RESULT {tmp_user.name.upper()} + CHECKING user: >Tmp$c4811< - without delimiters, CaMeL case + RESULT {tmp_user.name.upper()} + CHECKING user: >TMP$C4811< - without delimiters, UPPER case + RESULT {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + Your user name and password are not defined. Ask your database administrator to set up a Firebird login. + CHECKING user: >"TMP$C4811" - in double quotes, UPPER case + RESULT {tmp_user.name.upper()} + CHECKING role: >'Boss'< - in apostrophes, CaMeL case + RESULT {tmp_role.name.upper()} + CHECKING role: >'BOSS'< - in apostrophes, UPPER case + RESULT {tmp_role.name.upper()} + CHECKING role: >BosS< - without delimiters, CaMeL case + RESULT {tmp_role.name.upper()} + CHECKING role: >BOSS< - without delimiters, UPPER case + RESULT {tmp_role.name.upper()} + Statement failed, SQLSTATE = HY000 + exception + -{SQL_SCHEMA_PREFIX}{EXCEPTION_NAME} + -You've specified role: >"BoSs"< -- but your actual role is NONE. + -At procedure {SQL_SCHEMA_PREFIX}{STORED_PROC_NAME} + CHECKING role: >"BOSS"< - in double quotes, UPPER case + RESULT {tmp_role.name.upper()} + """ + + act.expected_stdout = expected_stdout + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0d7e7749c911c94fa4cc373bbe4c6eb0f9e87641 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 19:47:02 +0300 Subject: [PATCH 0882/1064] Added/Updated tests\bugs\core_4819_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4819_test.py | 128 +++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 51 deletions(-) diff --git a/tests/bugs/core_4819_test.py b/tests/bugs/core_4819_test.py index 4f94d3a5..6412961f 100644 --- a/tests/bugs/core_4819_test.py +++ b/tests/bugs/core_4819_test.py @@ -3,11 +3,16 @@ """ ID: issue-5116 ISSUE: 5116 -TITLE: EXECUTE PROCEDURE's RETURNING_VALUES and EXECUTE STATEMENT's INTO does not - check validity of assignments targets leading to bugcheck +TITLE: EXECUTE PROCEDURE's RETURNING_VALUES and EXECUTE STATEMENT's INTO does not check validity of assignments targets leading to bugcheck DESCRIPTION: JIRA: CORE-4819 FBTEST: bugs.core_4819 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -108,7 +113,7 @@ new.y as new_y; select - 'after update' msg, + 'after update' msg, cast(rdb$get_context('USER_SESSION', 'X_TRG_AIUD1') as int) as X_TRG_AIUD1, cast(rdb$get_context('USER_SESSION', 'Y_TRG_AIUD1') as int) as Y_TRG_AIUD1, cast(rdb$get_context('USER_SESSION', 'X_TRG_AIUD2') as int) as X_TRG_AIUD2, @@ -185,21 +190,28 @@ rollback; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +fb3x_checked_stdout = """ MSG initial state ID 1 X 3 Y 7 - + Statement failed, SQLSTATE = 42000 + attempted update of read-only column + Statement failed, SQLSTATE = 42000 + attempted update of read-only column + Statement failed, SQLSTATE = 42000 + attempted update of read-only column MSG after delete X_TRG_AIUD1 Y_TRG_AIUD1 X_TRG_AIUD2 Y_TRG_AIUD2 - - MSG after update + Statement failed, SQLSTATE = 42000 + attempted update of read-only column + MSG after update X_TRG_AIUD1 Y_TRG_AIUD1 X_TRG_AIUD2 @@ -207,71 +219,85 @@ ID 1 X 3 Y 7 -""" - -# version: 3.0 - -expected_stderr_1 = """ - Statement failed, SQLSTATE = 42000 - attempted update of read-only column - - Statement failed, SQLSTATE = 42000 - attempted update of read-only column - Statement failed, SQLSTATE = 42000 attempted update of read-only column - - Statement failed, SQLSTATE = 42000 - attempted update of read-only column - - Statement failed, SQLSTATE = 42000 - attempted update of read-only column - Statement failed, SQLSTATE = 42000 attempted update of read-only column - Statement failed, SQLSTATE = 42000 attempted update of read-only column """ -@pytest.mark.version('>=3.0,<4.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - -# version: 4.0 - -expected_stderr_2 = """ +fb5x_checked_stdout = """ + MSG initial state + ID 1 + X 3 + Y 7 Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.X - Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.X - Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.X - + MSG after delete + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.X - + MSG after update + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + ID 1 + X 3 + Y 7 Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.X - Statement failed, SQLSTATE = 42000 attempted update of read-only column CE.Y - Statement failed, SQLSTATE = 42000 attempted update of read-only column CE.Y """ -@pytest.mark.version('>=4.0') -def test_2(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) +fb6x_checked_stdout = """ + MSG initial state + ID 1 + X 3 + Y 7 + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."X" + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."X" + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."X" + MSG after delete + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."X" + MSG after update + X_TRG_AIUD1 + Y_TRG_AIUD1 + X_TRG_AIUD2 + Y_TRG_AIUD2 + ID 1 + X 3 + Y 7 + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."X" + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "CE"."Y" + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "CE"."Y" +""" + +@pytest.mark.version('>=3.0') +def test_1(act: Action): + act.expected_stdout = fb3x_checked_stdout if act.is_version('<4') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 8e470e760f8486f4168f334dca80a985f3b5862b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 19:49:55 +0300 Subject: [PATCH 0883/1064] Added/Updated tests\bugs\core_4826_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4826_test.py | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_4826_test.py b/tests/bugs/core_4826_test.py index 9a7a340b..47b88256 100644 --- a/tests/bugs/core_4826_test.py +++ b/tests/bugs/core_4826_test.py @@ -12,6 +12,10 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,27 +53,29 @@ act = isql_act('db', test_script, substitutions = [ ('^((?!SQLSTATE|sqltype).)*$', ''), ('[ \t]+', ' ') ] ) -expected_stdout = """ - 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 - 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - 04: sqltype: 580 INT64 Nullable scale: -4 subtype: 1 len: 8 - 05: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 - 06: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 - 07: sqltype: 570 SQL DATE Nullable scale: 0 subtype: 0 len: 4 - 08: sqltype: 560 TIME Nullable scale: 0 subtype: 0 len: 4 - 09: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 - 10: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - 11: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 4 charset: 4 UTF8 - 12: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 10 charset: 21 ISO8859_1 - 13: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 1 charset: 21 ISO8859_1 - 14: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 32760 charset: 21 ISO8859_1 - 15: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 52 WIN1251 - 16: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + 04: sqltype: 580 INT64 Nullable scale: -4 subtype: 1 len: 8 + 05: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + 06: sqltype: 482 FLOAT Nullable scale: 0 subtype: 0 len: 4 + 07: sqltype: 570 SQL DATE Nullable scale: 0 subtype: 0 len: 4 + 08: sqltype: 560 TIME Nullable scale: 0 subtype: 0 len: 4 + 09: sqltype: 510 TIMESTAMP Nullable scale: 0 subtype: 0 len: 8 + 10: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 + 11: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 4 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 + 12: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 10 charset: 21 {SQL_SCHEMA_PREFIX}ISO8859_1 + 13: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 1 charset: 21 {SQL_SCHEMA_PREFIX}ISO8859_1 + 14: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 32760 charset: 21 {SQL_SCHEMA_PREFIX}ISO8859_1 + 15: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 52 {SQL_SCHEMA_PREFIX}WIN1251 + 16: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From a5cdfffe0e18e49fa29fc7bac316891ec7641598 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 19:55:29 +0300 Subject: [PATCH 0884/1064] Added/Updated tests\bugs\core_4836_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4836_test.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_4836_test.py b/tests/bugs/core_4836_test.py index cc0e6bf4..1772d35b 100644 --- a/tests/bugs/core_4836_test.py +++ b/tests/bugs/core_4836_test.py @@ -12,6 +12,12 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,15 +55,22 @@ act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|C4836|R4836).)*$', '')]) -expected_stdout = """ - GRANT UPDATE (TEXT) ON TEST TO USER TMP$C4836 WITH GRANT OPTION - GRANT UPDATE (TEXT) ON TEST TO ROLE TMP$R4836 GRANTED BY TMP$C4836 - GRANT UPDATE (TEXT) ON TEST TO USER TMP$C4836 WITH GRANT OPTION -""" - +@pytest.mark.intl @pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User, tmp_role: Role): - act.expected_stdout = expected_stdout + + expected_stdout_5x = f""" + GRANT UPDATE (TEXT) ON TEST TO USER {tmp_user.name.upper()} WITH GRANT OPTION + GRANT UPDATE (TEXT) ON TEST TO ROLE {tmp_role.name.upper()} GRANTED BY {tmp_user.name.upper()} + GRANT UPDATE (TEXT) ON TEST TO USER {tmp_user.name.upper()} WITH GRANT OPTION + """ + + expected_stdout_6x = f""" + GRANT UPDATE (TEXT) ON PUBLIC.TEST TO {tmp_user.name.upper()} WITH GRANT OPTION + GRANT UPDATE (TEXT) ON PUBLIC.TEST TO ROLE {tmp_role.name.upper()} GRANTED BY {tmp_user.name.upper()} + GRANT UPDATE (TEXT) ON PUBLIC.TEST TO {tmp_user.name.upper()} WITH GRANT OPTION + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 051bf129e776c85322c6dd1e5152fa0f377c4f29 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 21:07:11 +0300 Subject: [PATCH 0885/1064] Added/Updated tests\bugs\core_4839_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4839_test.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_4839_test.py b/tests/bugs/core_4839_test.py index 7b0109b9..db066dc9 100644 --- a/tests/bugs/core_4839_test.py +++ b/tests/bugs/core_4839_test.py @@ -11,6 +11,12 @@ [15.05.2025] pzotov Added substitutions in order to suppress excessive lines produced by 'SHOW GRANTS': they may remain after some failed test teardown phases. + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,7 +24,7 @@ db = db_factory() -test_user = user_factory('db', name='tmp$c4839', password='123') +tmp_user = user_factory('db', name='tmp$c4839', password='123') test_script = """ recreate exception exc_foo 'Houston we have a problem: next sequence value is @1'; @@ -37,13 +43,17 @@ act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3.0') -def test_1(act: Action, test_user: User): - expected_out = """ - GRANT USAGE ON SEQUENCE GEN_BAR TO USER TMP$C4839 - GRANT USAGE ON EXCEPTION EXC_FOO TO USER TMP$C4839 +def test_1(act: Action, tmp_user: User): + expected_stdout_5x = f""" + GRANT USAGE ON SEQUENCE GEN_BAR TO USER {tmp_user.name.upper()} + GRANT USAGE ON EXCEPTION EXC_FOO TO USER {tmp_user.name.upper()} + """ + + expected_stdout_6x = f""" + GRANT USAGE ON SEQUENCE PUBLIC.GEN_BAR TO {tmp_user.name.upper()} + GRANT USAGE ON EXCEPTION PUBLIC.EXC_FOO TO {tmp_user.name.upper()} """ - act.expected_stdout = expected_out + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From cc2acc46f4b2279a04d9eb88c3dd198a165e8c13 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 21:14:24 +0300 Subject: [PATCH 0886/1064] Added/Updated tests\bugs\core_4846_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4846_test.py | 106 ++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/tests/bugs/core_4846_test.py b/tests/bugs/core_4846_test.py index 800e17a2..a8c10c0d 100644 --- a/tests/bugs/core_4846_test.py +++ b/tests/bugs/core_4846_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-4846 FBTEST: bugs.core_4846 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,17 +18,33 @@ db = db_factory() -test_script = """ - set term ^; - execute block as + +TRG_BODY_01 = """ begin - execute statement 'drop trigger muddy_trg'; - when any do begin end + new.id2 = coalesce( new.id2, gen_id(g, 1) ); end - ^ - set term ;^ - commit; +""" + +TRG_BODY_02 = """ + begin + new.id1 = coalesce( new.id1, gen_id(g, 1) ); + end +""" + +TRG_BODY_03 = """ + begin + insert into test1(id1, x1) values(old.id2, old.x2); + end +""" + +TRG_BODY_04 = """ + begin + if (not inserting) then insert into test2(id2, x2) values(old.id1, old.x1); + else insert into test2(id2, x2) values(new.id1, new.x1); + end +""" +test_script = f""" recreate table test1( id1 int primary key, x1 int); recreate table test2( id2 int primary key, x2 int); recreate sequence g; @@ -32,9 +52,7 @@ set term ^; create or alter trigger muddy_trg for test2 active before insert position 23184 as - begin - new.id2 = coalesce( new.id2, gen_id(g, 1) ); - end + {TRG_BODY_01} ^ set term ;^ commit; @@ -49,9 +67,7 @@ set term ^; create or alter trigger muddy_trg for test1 inactive before insert position 17895 as - begin - new.id1 = coalesce( new.id1, gen_id(g, 1) ); - end + {TRG_BODY_02} ^ set term ;^ commit; @@ -59,9 +75,7 @@ set term ^; recreate trigger muddy_trg for test2 inactive after delete position 11133 as - begin - insert into test1(id1, x1) values(old.id2, old.x2); - end + {TRG_BODY_03} ^ set term ;^ commit; @@ -70,10 +84,7 @@ set term ^; recreate trigger muddy_trg for test1 active before delete or update or insert position 24187 as - begin - if (not inserting) then insert into test2(id2, x2) values(old.id1, old.x1); - else insert into test2(id2, x2) values(new.id1, new.x1); - end + {TRG_BODY_04} ^ set term ;^ commit; @@ -83,41 +94,34 @@ act = isql_act('db', test_script, substitutions=[('\\+.*', ''), ('\\=.*', ''), ('Trigger text.*', '')]) -expected_stdout = """ - Triggers on Table TEST2: - MUDDY_TRG, Sequence: 23184, Type: BEFORE INSERT, Active - as - begin - new.id2 = coalesce( new.id2, gen_id(g, 1) ); - end +@pytest.mark.version('>=3.0') +def test_1(act: Action): + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + Triggers on Table {SQL_SCHEMA_PREFIX}TEST2: + {SQL_SCHEMA_PREFIX}MUDDY_TRG, Sequence: 23184, Type: BEFORE INSERT, Active + as + {TRG_BODY_01} - Triggers on Table TEST1: - MUDDY_TRG, Sequence: 17895, Type: BEFORE INSERT, Inactive - as - begin - new.id1 = coalesce( new.id1, gen_id(g, 1) ); - end - Triggers on Table TEST2: - MUDDY_TRG, Sequence: 11133, Type: AFTER DELETE, Inactive - as - begin - insert into test1(id1, x1) values(old.id2, old.x2); - end + Triggers on Table {SQL_SCHEMA_PREFIX}TEST1: + {SQL_SCHEMA_PREFIX}MUDDY_TRG, Sequence: 17895, Type: BEFORE INSERT, Inactive + as + {TRG_BODY_02} - Triggers on Table TEST1: - MUDDY_TRG, Sequence: 24187, Type: BEFORE DELETE OR UPDATE OR INSERT, Active - as - begin - if (not inserting) then insert into test2(id2, x2) values(old.id1, old.x1); - else insert into test2(id2, x2) values(new.id1, new.x1); - end -""" + Triggers on Table {SQL_SCHEMA_PREFIX}TEST2: + {SQL_SCHEMA_PREFIX}MUDDY_TRG, Sequence: 11133, Type: AFTER DELETE, Inactive + as + {TRG_BODY_03} + + Triggers on Table {SQL_SCHEMA_PREFIX}TEST1: + {SQL_SCHEMA_PREFIX}MUDDY_TRG, Sequence: 24187, Type: BEFORE DELETE OR UPDATE OR INSERT, Active + as + {TRG_BODY_04} + """ -@pytest.mark.version('>=3.0') -def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1a3b408b38f005adee22495e6aab2787fb57978a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 21:21:18 +0300 Subject: [PATCH 0887/1064] Added/Updated tests\bugs\core_4855_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4855_test.py | 99 ++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/tests/bugs/core_4855_test.py b/tests/bugs/core_4855_test.py index 10addeef..6efbb513 100644 --- a/tests/bugs/core_4855_test.py +++ b/tests/bugs/core_4855_test.py @@ -3,11 +3,14 @@ """ ID: issue-5151 ISSUE: 5151 -TITLE: Online validation during DML activity in other connection leads to message - "Error while trying to read from file" and "page in use during flush (210), file: cch.cpp line: 2672" +TITLE: Online validation during DML activity in other connection leads to message "Error while trying to read from file" and "page in use during flush (210), file: cch.cpp line: 2672" DESCRIPTION: JIRA: CORE-4855 FBTEST: bugs.core_4855 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -25,48 +28,26 @@ act = python_act('db', substitutions=substitutions) -expected_stdout = """ -Iteration #1: -21:16:28.31 Validation started -21:16:28.31 Relation 128 (TEST) -21:16:29.31 Acquire relation lock failed -21:16:29.31 Relation 128 (TEST) : 1 ERRORS found -21:16:30.04 Relation 129 (STOP) -21:16:30.04 process pointer page 0 of 1 -21:16:30.04 Relation 129 (STOP) is ok -21:16:30.04 Validation finished -Iteration #2: -21:16:32.46 Validation started -21:16:32.46 Relation 128 (TEST) -21:16:33.46 Acquire relation lock failed -21:16:33.46 Relation 128 (TEST) : 1 ERRORS found -21:16:35.09 Relation 129 (STOP) -21:16:35.09 process pointer page 0 of 1 -21:16:35.09 Relation 129 (STOP) is ok -21:16:35.09 Validation finished -INSERTED_ROWS OK, LOT OF. -""" - heavy_script = """ -recreate sequence g; -recreate table test(id int, s varchar( 36 ) unique using index test_s_unq); -recreate table stop(id int); -commit; -set list on; -set transaction read committed; -set term ^; -execute block returns( inserted_rows varchar(20) ) as -begin - while ( not exists(select * from stop) ) do - begin - insert into test(id, s) values( gen_id(g,1), rpad('', 36, uuid_to_char(gen_uuid())) ); - end - inserted_rows = iif(gen_id(g,0) > 0, 'OK, LOT OF.', 'FAIL: ZERO!'); - suspend; -end -^ -set term ;^ -commit; + recreate sequence g; + recreate table test(id int, s varchar( 36 ) unique using index test_s_unq); + recreate table stop(id int); + commit; + set list on; + set transaction read committed; + set term ^; + execute block returns( inserted_rows varchar(20) ) as + begin + while ( not exists(select * from stop) ) do + begin + insert into test(id, s) values( gen_id(g,1), rpad('', 36, uuid_to_char(gen_uuid())) ); + end + inserted_rows = iif(gen_id(g,0) > 0, 'OK, LOT OF.', 'FAIL: ZERO!'); + suspend; + end + ^ + set term ;^ + commit; """ heavy_script_file = temp_file('heavy_script.sql') @@ -77,12 +58,15 @@ def test_1(act: Action, heavy_script_file: Path, heavy_output: Path, capsys): # Preparing script for ISQL that will do 'heavy DML' heavy_script_file.write_text(heavy_script) with open(heavy_output, mode='w') as heavy_out: + ############################################# + ### a s y n c l a u n c h i s q l ### + ############################################# p_heavy_sql = subprocess.Popen([act.vars['isql'], '-i', str(heavy_script_file), '-user', act.db.user, '-password', act.db.password, act.db.dsn], stdout=heavy_out, stderr=subprocess.STDOUT) try: - time.sleep(4) + time.sleep(4) # todo: reimplement this via query to mon$ tables every 0.1 second # Run validation twice with act.connect_server() as srv: print('Iteration #1:') @@ -99,6 +83,33 @@ def test_1(act: Action, heavy_script_file: Path, heavy_output: Path, capsys): print(heavy_output.read_text()) # Check act.reset() + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_TEST_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' + TABLE_STOP_NAME = 'STOP' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"STOP"' + + expected_stdout = f""" + Iteration #1: + 21:16:28.31 Validation started + 21:16:28.31 Relation 128 ({TABLE_TEST_NAME}) + 21:16:29.31 Acquire relation lock failed + 21:16:29.31 Relation 128 ({TABLE_TEST_NAME}) : 1 ERRORS found + 21:16:30.04 Relation 129 ({TABLE_STOP_NAME}) + 21:16:30.04 process pointer page 0 of 1 + 21:16:30.04 Relation 129 ({TABLE_STOP_NAME}) is ok + 21:16:30.04 Validation finished + Iteration #2: + 21:16:32.46 Validation started + 21:16:32.46 Relation 128 ({TABLE_TEST_NAME}) + 21:16:33.46 Acquire relation lock failed + 21:16:33.46 Relation 128 ({TABLE_TEST_NAME}) : 1 ERRORS found + 21:16:35.09 Relation 129 ({TABLE_STOP_NAME}) + 21:16:35.09 process pointer page 0 of 1 + 21:16:35.09 Relation 129 ({TABLE_STOP_NAME}) is ok + 21:16:35.09 Validation finished + INSERTED_ROWS OK, LOT OF. + """ + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 9d518d47bea9bd9532e64dbaca12d20b2e4b1e5c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 21:24:40 +0300 Subject: [PATCH 0888/1064] Added/Updated tests\bugs\core_4884_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4884_test.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_4884_test.py b/tests/bugs/core_4884_test.py index 69c56adf..ba3c1967 100644 --- a/tests/bugs/core_4884_test.py +++ b/tests/bugs/core_4884_test.py @@ -9,6 +9,10 @@ Batch file that generates .sql with arbitrary level of begin..end statements can be seen in the traker. JIRA: CORE-4884 FBTEST: bugs.core_4884 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -1568,16 +1572,19 @@ substitutions=[('exception [0-9]+', 'exception'), ('time=.*', ''), ('-At block line: [\\d]+, col: [\\d]+', '-At block line')]) -expected_stderr = """ - Statement failed, SQLSTATE = HY000 - exception 4 - -EX_TEST - -Hi from Mariana Trench, depth=511, time=2015-08-24 13:47:25.1330 - -At block line: 1026, col: 5 -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + EXCEPTION_NAME = 'EX_TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"EX_TEST"' + expected_stderr = f""" + Statement failed, SQLSTATE = HY000 + exception 4 + -{EXCEPTION_NAME} + -Hi from Mariana Trench, depth=511, time=2015-08-24 13:47:25.1330 + -At block line: 1026, col: 5 + """ + act.expected_stderr = expected_stderr act.execute() assert act.clean_stderr == act.clean_expected_stderr From cab25d5fb4305434d2ec33524270d0a6bd6e88b2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 22:55:23 +0300 Subject: [PATCH 0889/1064] Added/Updated tests\bugs\core_4904_test.py: DISABLED execution on FB 6.x - see notes. --- tests/bugs/core_4904_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_4904_test.py b/tests/bugs/core_4904_test.py index 18d7bafa..b873e20e 100644 --- a/tests/bugs/core_4904_test.py +++ b/tests/bugs/core_4904_test.py @@ -14,6 +14,10 @@ 4. Start validation of database: index should NOT be corrupted in its report. JIRA: CORE-4904 FBTEST: bugs.core_4904 +NOTES: + [30.06.2025] pzotov + Test can not be executed on FB 6.x for suitable time because minimal page_size in this version is 8192. + Number of rows that is needed to be inserted in index with key length = ~2K is too large. """ import pytest @@ -61,7 +65,7 @@ Validation finished """ -@pytest.mark.version('>=3.0') +@pytest.mark.version('>=3.0,<6') def test_1(act: Action, capsys): # Move database to FW = OFF in order to increase speed of insertions and output its header info: with act.connect_server() as srv: From 8a8117d4415deb3aecd99d00416061fd01c50ea0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 22:57:58 +0300 Subject: [PATCH 0890/1064] Added/Updated tests\bugs\core_4905_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4905_test.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_4905_test.py b/tests/bugs/core_4905_test.py index bfe6ec73..f117c490 100644 --- a/tests/bugs/core_4905_test.py +++ b/tests/bugs/core_4905_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4905 FBTEST: bugs.core_4905 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,15 +35,17 @@ where p.rdb$procedure_name = upper('SP_TEST'); """ -act = isql_act('db', test_script, substitutions=[('SP_BLR_BLOB.*', '')]) +act = isql_act('db', test_script, substitutions = [ ('[ \t]+', ' '), ('SP_BLR_BLOB.*', '')] ) -expected_stdout = """ +expected_stdout_5x = """ blr_version5,blr_begin, blr_message, 0, 2,0, blr_column_name, 0, 9, 'R','D','B','$','T','Y','P','E','S', 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E', blr_short, 0, blr_message, 1, 1,0, blr_short, 0, blr_receive, 0, blr_begin, blr_stall, blr_label, 0, blr_begin, blr_end, blr_end, blr_send, 1, blr_begin, blr_assignment, blr_literal, blr_short, 0, 0,0, blr_parameter, 1, 0,0, blr_end, blr_end, blr_eoc """ +expected_stdout_6x = """ + blr_version5,blr_begin, blr_message, 0, 2,0, blr_column_name3, 0, 6, 'S','Y','S','T','E','M', 9, 'R','D','B','$','T','Y','P','E','S', 14, 'R','D','B','$','F','I','E','L','D','_','N','A','M','E',0, blr_short, 0, blr_message, 1, 1,0, blr_short, 0, blr_receive, 0, blr_begin, blr_stall, blr_label, 0, blr_begin, blr_end, blr_end, blr_send, 1, blr_begin, blr_assignment, blr_literal, blr_short, 0, 0,0, blr_parameter, 1, 0,0, blr_end, blr_end, blr_eoc +""" @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 9ec3c9bc772e42c7a71c60fac2dfba8d3dca6cdd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:08:39 +0300 Subject: [PATCH 0891/1064] Added/Updated tests\bugs\core_4917_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4917_test.py | 73 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/tests/bugs/core_4917_test.py b/tests/bugs/core_4917_test.py index 9a520da9..ccb4c204 100644 --- a/tests/bugs/core_4917_test.py +++ b/tests/bugs/core_4917_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-4917 FBTEST: bugs.core_4917 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x + Removed 'SHOW DOMAIN' command as its output has no matter for this test. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -45,47 +50,41 @@ -- this also should FAIL becase new domain name is written in UPPER case (despite quotes): alter domain "rdb$2" to "RDB$3"; - show domain; - """ act = isql_act('db', test_script) -expected_stdout = """ - rdb$2 -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -CREATE DOMAIN RDB$1 failed - -SQL error code = -637 - -Implicit domain name RDB$1 not allowed in user created domain - - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -CREATE DOMAIN RDB$2 failed - -SQL error code = -637 - -Implicit domain name RDB$2 not allowed in user created domain - - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -ALTER DOMAIN rdb$2 failed - -SQL error code = -637 - -Implicit domain name RDB$3 not allowed in user created domain - - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -ALTER DOMAIN rdb$2 failed - -SQL error code = -637 - -Implicit domain name RDB$3 not allowed in user created domain -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + DOMAIN_1_UPPER = 'RDB$1' if act.is_version('<6') else '"RDB$1"' + DOMAIN_2_UPPER = 'RDB$2' if act.is_version('<6') else '"RDB$2"' + DOMAIN_2_LOWER = 'rdb$2' if act.is_version('<6') else '"rdb$2"' + + expected_stdout = f""" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE DOMAIN {SQL_SCHEMA_PREFIX}{DOMAIN_1_UPPER} failed + -SQL error code = -637 + -Implicit domain name {SQL_SCHEMA_PREFIX}{DOMAIN_1_UPPER} not allowed in user created domain + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE DOMAIN {SQL_SCHEMA_PREFIX}{DOMAIN_2_UPPER} failed + -SQL error code = -637 + -Implicit domain name {SQL_SCHEMA_PREFIX}{DOMAIN_2_UPPER} not allowed in user created domain + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN {SQL_SCHEMA_PREFIX}{DOMAIN_2_LOWER} failed + -SQL error code = -637 + -Implicit domain name RDB$3 not allowed in user created domain + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER DOMAIN {SQL_SCHEMA_PREFIX}{DOMAIN_2_LOWER} failed + -SQL error code = -637 + -Implicit domain name RDB$3 not allowed in user created domain + """ + + act.expected_stdout = expected_stdout # _5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0d3c454d0a6dc214ce73198e2274a818e50fd731 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:17:17 +0300 Subject: [PATCH 0892/1064] Added/Updated tests\bugs\core_4921_test.py: Re-implemented. Explained form is used for all checked FB versions, including 3.x. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4921_test.py | 160 ++++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_4921_test.py b/tests/bugs/core_4921_test.py index 16e593b2..f8fd2113 100644 --- a/tests/bugs/core_4921_test.py +++ b/tests/bugs/core_4921_test.py @@ -5,12 +5,20 @@ ISSUE: 1956 TITLE: Predicate IS [NOT] DISTINCT FROM is not pushed into unions/aggregates thus causing sub-optimal plans DESCRIPTION: - Implementation for 3.0 does NOT use 'set explain on' (decision after discuss with Dmitry, letter 02-sep-2015 15:42). - Test only checks that: - 1) in case when NATURAL scan occured currently index T*_SINGLE_X is used; - 2) in case when it was only PARTIAL matching index Y*_COMPOUND_X is in use. + Implementation for 3.0 does NOT use 'set explain on' (decision after discuss with Dmitry, letter 02-sep-2015 15:42). + Test only checks that: + 1) in case when NATURAL scan occured currently index T*_SINGLE_X is used; + 2) in case when it was only PARTIAL matching index Y*_COMPOUND_X is in use. JIRA: CORE-4921 FBTEST: bugs.core_4921 +NOTES: + [30.06.2025] pzotov + Re-implemented. Explained form is used for all checked FB versions, including 3.x + + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -42,25 +50,137 @@ commit; """ -db = db_factory(init=init_script) +db = db_factory(init = init_script) -test_script = """ - set planonly; - select * from v_test where x is not distinct from 1; - select * from v_test where x = 1 and y is not distinct from 1; - set planonly; -""" +act = python_act('db', substitutions=[('record length.*', ''), ('key length.*', '')]) -act = isql_act('db', test_script) +#----------------------------------------------------------- -expected_stdout = """ - PLAN (V_TEST T1 INDEX (T1_SINGLE_X), V_TEST T2 INDEX (T2_SINGLE_X), V_TEST T3 INDEX (T3_SINGLE_X)) - PLAN (V_TEST T1 INDEX (T1_COMPOUND_X_Y), V_TEST T2 INDEX (T2_COMPOUND_X_Y), V_TEST T3 INDEX (T3_COMPOUND_X_Y)) -""" +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- @pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout +def test_1(act: Action, capsys): + qry_map = { + 1000 : + """ + select * from v_test where x is not distinct from 1 + """ + , + 2000 : + """ + select * from v_test where x = 1 and y is not distinct from 1 + """ + } + + with act.db.connect() as con: + cur = con.cursor() + + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) + print(v) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + print('') + + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + #rs = cur.execute(ps) + #for r in rs: + # print(r[0], r[1]) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + + expected_stdout_5x = f""" + {qry_map[1000]} + Select Expression + ....-> Filter + ........-> Union + ............-> Filter + ................-> Table "T1" as "V_TEST T1" Access By ID + ....................-> Bitmap + ........................-> Index "T1_SINGLE_X" Range Scan (full match) + ............-> Filter + ................-> Table "T2" as "V_TEST T2" Access By ID + ....................-> Bitmap + ........................-> Index "T2_SINGLE_X" Range Scan (full match) + ............-> Filter + ................-> Table "T3" as "V_TEST T3" Access By ID + ....................-> Bitmap + ........................-> Index "T3_SINGLE_X" Range Scan (full match) + + + {qry_map[2000]} + Select Expression + ....-> Filter + ........-> Union + ............-> Filter + ................-> Table "T1" as "V_TEST T1" Access By ID + ....................-> Bitmap + ........................-> Index "T1_COMPOUND_X_Y" Range Scan (full match) + ............-> Filter + ................-> Table "T2" as "V_TEST T2" Access By ID + ....................-> Bitmap + ........................-> Index "T2_COMPOUND_X_Y" Range Scan (full match) + ............-> Filter + ................-> Table "T3" as "V_TEST T3" Access By ID + ....................-> Bitmap + ........................-> Index "T3_COMPOUND_X_Y" Range Scan (full match) + """ + + expected_stdout_6x = f""" + {qry_map[1000]} + Select Expression + ....-> Filter + ........-> Union + ............-> Filter + ................-> Table "PUBLIC"."T1" as "PUBLIC"."V_TEST" "PUBLIC"."T1" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T1_SINGLE_X" Range Scan (full match) + ............-> Filter + ................-> Table "PUBLIC"."T2" as "PUBLIC"."V_TEST" "PUBLIC"."T2" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T2_SINGLE_X" Range Scan (full match) + ............-> Filter + ................-> Table "PUBLIC"."T3" as "PUBLIC"."V_TEST" "PUBLIC"."T3" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T3_SINGLE_X" Range Scan (full match) + + {qry_map[2000]} + Select Expression + ....-> Filter + ........-> Union + ............-> Filter + ................-> Table "PUBLIC"."T1" as "PUBLIC"."V_TEST" "PUBLIC"."T1" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T1_COMPOUND_X_Y" Range Scan (full match) + ............-> Filter + ................-> Table "PUBLIC"."T2" as "PUBLIC"."V_TEST" "PUBLIC"."T2" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T2_COMPOUND_X_Y" Range Scan (full match) + ............-> Filter + ................-> Table "PUBLIC"."T3" as "PUBLIC"."V_TEST" "PUBLIC"."T3" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."T3_COMPOUND_X_Y" 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 From 14cd827b6bc0e49b4228c632b6dc64a6cf9d9085 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:24:43 +0300 Subject: [PATCH 0893/1064] Added/Updated tests\bugs\core_4927_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4927_test.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_4927_test.py b/tests/bugs/core_4927_test.py index d40e7173..3d0c1534 100644 --- a/tests/bugs/core_4927_test.py +++ b/tests/bugs/core_4927_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-4927 FBTEST: bugs.core_4927 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -84,14 +90,14 @@ db = db_factory(init=init_script) -act = python_act('db', substitutions=[('^((?!HEADER_|DETAIL_).)*$', ''), - ('HEADER_2100.*', 'HEADER_2100'), - ('DETAIL_2100.*', 'DETAIL_2100')]) +substitutions = [ + ('^((?!HEADER_|DETAIL_).)*$', ''), + ('(")?HEADER_2100(")?.*', 'HEADER_2100'), + ('(")?DETAIL_2100(")?.*', 'DETAIL_2100'), + ('"PUBLIC"', 'PUBLIC') +] -expected_stdout = """ - HEADER_2100 - DETAIL_2100 -""" +act = python_act('db', substitutions = substitutions) trace = ['time_threshold = 0', 'log_initfini = false', @@ -104,7 +110,17 @@ def test_1(act: Action, capsys): with act.trace(db_events=trace): act.isql(switches=[], input='set list on; select result from sp_test;') - # Check - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + HEADER_2100 + DETAIL_2100 + """ + + expected_stdout_6x = """ + PUBLIC.HEADER_2100 + PUBLIC.DETAIL_2100 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.trace_to_stdout() assert act.clean_stdout == act.clean_expected_stdout From 2b8f9a4296a5302db39b1520fd7f4f3f52742aea Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:43:23 +0300 Subject: [PATCH 0894/1064] Added/Updated tests\bugs\core_4940_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4940_test.py | 74 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_4940_test.py b/tests/bugs/core_4940_test.py index add53583..2a2f81ef 100644 --- a/tests/bugs/core_4940_test.py +++ b/tests/bugs/core_4940_test.py @@ -19,44 +19,78 @@ db = db_factory() -test_script = """ - -- 1. Specify 'deterministic' flag - it should be reflected in SHOW command: - set term ^; - create or alter function fn_infinity returns bigint deterministic as +FUNC_DDL_1 = """ begin return 9223372036854775807; end +""" + +FUNC_DDL_2 = """ + begin + return rand() * 9223372036854775807; + end +""" + +test_script = f""" + -- 1. Specify 'deterministic' flag - it should be reflected in SHOW command: + set term ^; + create or alter function fn_test returns bigint deterministic as + {FUNC_DDL_1} ^ set term ;^ commit; - show function fn_infinity; + show function fn_test; -- 2. Remove 'deterministic' flag - it also should be reflected in SHOW command: set term ^; - alter function fn_infinity returns bigint as - begin - return 9223372036854775807; - end + alter function fn_test returns bigint as + {FUNC_DDL_2} ^ set term ;^ commit; - show function fn_infinity; + show function fn_test; """ -act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|[Ff]unction|[Dd]eterministic).)*$', '')]) - -expected_stdout = """ - Deterministic function - Function text: - - Function text: -""" +substitutions = [('===.*', '')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = f""" + Deterministic function + Function text: + {FUNC_DDL_1} + + Parameters: + OUTPUT BIGINT + + Function text: + {FUNC_DDL_2} + + Parameters: + OUTPUT BIGINT + """ + + expected_stdout_6x = f""" + Function: PUBLIC.FN_TEST + Deterministic function + Function text: + {FUNC_DDL_1} + + Parameters: + OUTPUT BIGINT + + Function: PUBLIC.FN_TEST + Function text: + {FUNC_DDL_2} + + Parameters: + OUTPUT BIGINT + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 9d04e99042a4743044ae8fa4acf2b09c7b806e9f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:52:59 +0300 Subject: [PATCH 0895/1064] Added/Updated tests\bugs\core_4980_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4980_test.py | 115 +++++++++++++++++------------------ 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/tests/bugs/core_4980_test.py b/tests/bugs/core_4980_test.py index 67d9e156..3191130f 100644 --- a/tests/bugs/core_4980_test.py +++ b/tests/bugs/core_4980_test.py @@ -10,73 +10,68 @@ Query to table TEST should be denied, but queries to RDB-tables should run OK and display their data. JIRA: CORE-4980 FBTEST: bugs.core_4980 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ - +import locale import pytest from firebird.qa import * db = db_factory() - tmp_user = user_factory('db', name='tmp_c4980', password='123') -test_script = """ - set wng off; - - recreate table test(id int); - commit; - insert into test values(1); - commit; - - connect '$(DSN)' user tmp_c4980 password '123'; - - -- All subsequent statements (being issued by TMP_C4980) failed on 3.0.0.32134 and runs OK on build 32136: - set list on; +act = isql_act('db') - select current_user as who_am_i from rdb$database; - select current_user as who_am_i, r.rdb$character_set_name from rdb$database r; - select current_user as who_am_i, r.rdb$relation_name from rdb$relations r order by rdb$relation_id rows 1; - select current_user as who_am_i, t.id from test t; -- this should ALWAYS fail because this is non-system table. - commit; -""" - -act = isql_act('db', test_script) - -expected_stdout = """ - WHO_AM_I TMP_C4980 - WHO_AM_I TMP_C4980 - RDB$CHARACTER_SET_NAME NONE - WHO_AM_I TMP_C4980 - RDB$RELATION_NAME RDB$PAGES -""" - -# version: 3.0 - -expected_stderr_1 = """ - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST -""" - -@pytest.mark.version('>=3.0,<4.0') +@pytest.mark.version('>=3.0') def test_1(act: Action, tmp_user: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - -# version: 4.0 - -expected_stderr_2 = """ - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is TMP_C4980 -""" - -@pytest.mark.version('>=4.0') -def test_2(act: Action, tmp_user: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + test_script = f""" + set wng off; + + recreate table test(id int); + commit; + insert into test values(1); + commit; + + connect '{act.db.dsn}' user {tmp_user.name.upper()} password '{tmp_user.password}'; + + -- All subsequent statements (being issued by TMP_C4980) failed on 3.0.0.32134 and runs OK on build 32136: + set list on; + + select current_user as who_am_i from rdb$database; + select current_user as who_am_i, r.rdb$character_set_name from rdb$database r; + select current_user as who_am_i, r.rdb$relation_name from rdb$relations r order by rdb$relation_id rows 1; + select current_user as who_am_i, t.id from test t; -- this should ALWAYS fail because this is non-system table. + commit; + """ + + expected_stdout_3x = f""" + WHO_AM_I {tmp_user.name.upper()} + WHO_AM_I {tmp_user.name.upper()} + RDB$CHARACTER_SET_NAME NONE + WHO_AM_I {tmp_user.name.upper()} + RDB$RELATION_NAME RDB$PAGES + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE TEST + """ + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' + expected_stdout_5x = f""" + WHO_AM_I {tmp_user.name.upper()} + WHO_AM_I {tmp_user.name.upper()} + RDB$CHARACTER_SET_NAME NONE + WHO_AM_I {tmp_user.name.upper()} + RDB$RELATION_NAME RDB$PAGES + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_NAME} + -Effective user is {tmp_user.name.upper()} + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x + act.isql(switches = ['-q'], input = test_script, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout From 6c48775f49ce89b32d1694e9f15b6fa5ccd79264 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:57:52 +0300 Subject: [PATCH 0896/1064] Added/Updated tests\bugs\core_4985_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_4985_test.py | 47 ++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/tests/bugs/core_4985_test.py b/tests/bugs/core_4985_test.py index 91f71db3..43a723b7 100644 --- a/tests/bugs/core_4985_test.py +++ b/tests/bugs/core_4985_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-4985 FBTEST: bugs.core_4985 +NOTES: + [30.06.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -38,29 +43,29 @@ commit; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - Records affected: 7 - WHO_AM_I TMP$C4985 - Records affected: 1 -""" +@pytest.mark.version('>=4.0') +def test_1(act: Action, tmp_user: User): -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is TMP$C4985 + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' + expected_stdout = f""" + Records affected: 7 - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is TMP$C4985 -""" + WHO_AM_I {tmp_user.name.upper()} + Records affected: 1 -@pytest.mark.version('>=4.0') -def test_1(act: Action, tmp_user: User): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_NAME} + -Effective user is {tmp_user.name.upper()} + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_NAME} + -Effective user is {tmp_user.name.upper()} + """ + + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0bf0f78ccd30fa3ccdff80aafe7fb7355903a194 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Mon, 30 Jun 2025 23:58:54 +0300 Subject: [PATCH 0897/1064] minor change: adjusted notes --- tests/bugs/core_4980_test.py | 2 +- tests/bugs/core_4985_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4980_test.py b/tests/bugs/core_4980_test.py index 3191130f..4e76fb58 100644 --- a/tests/bugs/core_4980_test.py +++ b/tests/bugs/core_4980_test.py @@ -12,7 +12,7 @@ FBTEST: bugs.core_4980 NOTES: [30.06.2025] pzotov - Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. diff --git a/tests/bugs/core_4985_test.py b/tests/bugs/core_4985_test.py index 43a723b7..945dac8b 100644 --- a/tests/bugs/core_4985_test.py +++ b/tests/bugs/core_4985_test.py @@ -9,7 +9,7 @@ FBTEST: bugs.core_4985 NOTES: [30.06.2025] pzotov - Added 'SQL_SCHEMA_PREFIX' and variables to store domain names - to be substituted in expected_* on FB 6.x + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ From 33acbd1d0c64d35ae00478bd15053c14f86b353f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 00:06:18 +0300 Subject: [PATCH 0898/1064] Added/Updated tests\bugs\core_1725_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_1725_test.py | 226 +++++++++++++++++++++++------------ 1 file changed, 148 insertions(+), 78 deletions(-) diff --git a/tests/bugs/core_1725_test.py b/tests/bugs/core_1725_test.py index ef821291..2632bf7f 100644 --- a/tests/bugs/core_1725_test.py +++ b/tests/bugs/core_1725_test.py @@ -46,6 +46,12 @@ Checked on: 6.0.0.511-c4bc943; 5.0.2.1547-1e08f5e; 4.0.0.1384-fea7c61 (17-jan-2019, just after fix); 3.0.13.33793-3e62713 + + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import locale @@ -306,89 +312,153 @@ def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): ########################################################################### - act.expected_stdout = """ + expected_stdout_5x = """ restore_log - gbak:finishing, closing, and going home - gbak:adjusting the ONLINE and FORCED WRITES flags - + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags check_metadata - RDB$INDEX_NAME TEST_X - RDB$INDEX_INACTIVE 1 - RDB$INDEX_NAME TEST_Y - RDB$INDEX_INACTIVE 1 - Records affected: 2 - - RDB$PACKAGE_NAME - SP_NAME SP_INIT - SP_VALID_BLR 1 - RDB$PACKAGE_NAME - SP_NAME SP_MAIN - SP_VALID_BLR 1 - RDB$PACKAGE_NAME - SP_NAME SP_WORKER - SP_VALID_BLR 1 - RDB$PACKAGE_NAME PG_TEST - SP_NAME PG_SP_WORKER - SP_VALID_BLR 1 - Records affected: 4 - - RDB$PACKAGE_NAME - FN_NAME FN_INIT - FN_VALID_BLR 1 - RDB$PACKAGE_NAME - FN_NAME FN_MAIN - FN_VALID_BLR 1 - RDB$PACKAGE_NAME - FN_NAME FN_WORKER - FN_VALID_BLR 1 - RDB$PACKAGE_NAME PG_TEST - FN_NAME PG_FN_WORKER - FN_VALID_BLR 1 - Records affected: 4 - - RDB$TRIGGER_NAME TEST_BI - RDB$TRIGGER_INACTIVE 0 - TG_VALID_BLR 1 - Records affected: 1 + RDB$INDEX_NAME TEST_X + RDB$INDEX_INACTIVE 1 + RDB$INDEX_NAME TEST_Y + RDB$INDEX_INACTIVE 1 + Records affected: 2 + RDB$PACKAGE_NAME + SP_NAME SP_INIT + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_MAIN + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_WORKER + SP_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + SP_NAME PG_SP_WORKER + SP_VALID_BLR 1 + Records affected: 4 + RDB$PACKAGE_NAME + FN_NAME FN_INIT + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_MAIN + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_WORKER + FN_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + FN_NAME PG_FN_WORKER + FN_VALID_BLR 1 + Records affected: 4 + RDB$TRIGGER_NAME TEST_BI + RDB$TRIGGER_INACTIVE 0 + TG_VALID_BLR 1 + Records affected: 1 + check_avail_db_objects + select * from v_worker; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset + -there is no index TEST_Y for table TEST + execute procedure sp_main; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure SP_MAIN's BLR + -Error while parsing procedure SP_WORKER's BLR + invalid request BLR at offset + -there is no index TEST_X for table TEST + select fn_main() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function FN_MAIN's BLR + -Error while parsing function FN_WORKER's BLR + invalid request BLR at offset + -there is no index TEST_X for table TEST + execute procedure pg_test.pg_sp_worker; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure PG_TEST.PG_SP_WORKER's BLR + invalid request BLR at offset + -there is no index TEST_X for table TEST + select pg_test.pg_fn_worker() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function PG_TEST.PG_FN_WORKER's BLR + invalid request BLR at offset + -there is no index TEST_X for table TEST + insert into test(id, x, y) values(-1, -1, -1) returning id, x, y; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset + -there is no index TEST_X for table TEST + """ + expected_stdout_6x = """ + restore_log + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + check_metadata + RDB$INDEX_NAME TEST_X + RDB$INDEX_INACTIVE 1 + RDB$INDEX_NAME TEST_Y + RDB$INDEX_INACTIVE 1 + Records affected: 2 + RDB$PACKAGE_NAME + SP_NAME SP_INIT + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_MAIN + SP_VALID_BLR 1 + RDB$PACKAGE_NAME + SP_NAME SP_WORKER + SP_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + SP_NAME PG_SP_WORKER + SP_VALID_BLR 1 + Records affected: 4 + RDB$PACKAGE_NAME + FN_NAME FN_INIT + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_MAIN + FN_VALID_BLR 1 + RDB$PACKAGE_NAME + FN_NAME FN_WORKER + FN_VALID_BLR 1 + RDB$PACKAGE_NAME PG_TEST + FN_NAME PG_FN_WORKER + FN_VALID_BLR 1 + Records affected: 4 + RDB$TRIGGER_NAME TEST_BI + RDB$TRIGGER_INACTIVE 0 + TG_VALID_BLR 1 + Records affected: 1 check_avail_db_objects - select * from v_worker; - Statement failed, SQLSTATE = 42000 - invalid request BLR at offset 35 - -there is no index TEST_Y for table TEST - - execute procedure sp_main; - Statement failed, SQLSTATE = 2F000 - Error while parsing procedure SP_MAIN's BLR - -Error while parsing procedure SP_WORKER's BLR - -invalid request BLR at offset 66 - -there is no index TEST_X for table TEST - - select fn_main() from rdb$database; - Statement failed, SQLSTATE = 2F000 - Error while parsing function FN_MAIN's BLR - -Error while parsing function FN_WORKER's BLR - -invalid request BLR at offset 72 - -there is no index TEST_X for table TEST - - execute procedure pg_test.pg_sp_worker; - Statement failed, SQLSTATE = 2F000 - Error while parsing procedure PG_TEST.PG_SP_WORKER's BLR - -invalid request BLR at offset 66 - -there is no index TEST_X for table TEST - - select pg_test.pg_fn_worker() from rdb$database; - Statement failed, SQLSTATE = 2F000 - Error while parsing function PG_TEST.PG_FN_WORKER's BLR - -invalid request BLR at offset 72 - -there is no index TEST_X for table TEST - - insert into test(id, x, y) values(-1, -1, -1) returning id, x, y; - Statement failed, SQLSTATE = 42000 - invalid request BLR at offset - -there is no index TEST_X for table TEST + select * from v_worker; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_Y" for table "PUBLIC"."TEST" + execute procedure sp_main; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure "PUBLIC"."SP_MAIN"'s BLR + -Error while parsing procedure "PUBLIC"."SP_WORKER"'s BLR + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_X" for table "PUBLIC"."TEST" + select fn_main() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function "PUBLIC"."FN_MAIN"'s BLR + -Error while parsing function "PUBLIC"."FN_WORKER"'s BLR + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_X" for table "PUBLIC"."TEST" + execute procedure pg_test.pg_sp_worker; + Statement failed, SQLSTATE = 2F000 + Error while parsing procedure "PUBLIC"."PG_TEST"."PG_SP_WORKER"'s BLR + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_X" for table "PUBLIC"."TEST" + select pg_test.pg_fn_worker() from rdb$database; + Statement failed, SQLSTATE = 2F000 + Error while parsing function "PUBLIC"."PG_TEST"."PG_FN_WORKER"'s BLR + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_X" for table "PUBLIC"."TEST" + insert into test(id, x, y) values(-1, -1, -1) returning id, x, y; + Statement failed, SQLSTATE = 42000 + invalid request BLR at offset + -there is no index "PUBLIC"."TEST_X" for table "PUBLIC"."TEST" """ + + 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 - act.reset() From 0bffc306877e5d552f410d488e45ba34ec088c75 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 00:13:13 +0300 Subject: [PATCH 0899/1064] Added/Updated tests\bugs\core_3176_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_3176_test.py | 57 ++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_3176_test.py b/tests/bugs/core_3176_test.py index a2acc40f..1294bd1f 100644 --- a/tests/bugs/core_3176_test.py +++ b/tests/bugs/core_3176_test.py @@ -3,47 +3,52 @@ """ ID: issue-3550 ISSUE: 3550 -TITLE: View with "subselect" column join table and not use index +TITLE: Index is not used when view has "subselect" column DESCRIPTION: JIRA: CORE-3176 FBTEST: bugs.core_3176 +NOTES: + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """CREATE TABLE TMP -( - ID Integer NOT NULL, - CONSTRAINT PK_TMP_1 PRIMARY KEY (ID) -); -COMMIT; -CREATE VIEW TMP_VIEW (ID1, ID2) -AS -SELECT 1,(SELECT 1 FROM RDB$DATABASE) FROM RDB$DATABASE; -COMMIT;""" - -db = db_factory(init=init_script) - -test_script = """SET PLAN ON; -SELECT * FROM tmp_view TV LEFT JOIN tmp T ON T.id=TV.id2; +db = db_factory() + +test_script = """ + create table tmp ( + id int not null, + constraint pk_tmp_1 primary key (id) + ); + create view tmp_view as + select 1 as id1, (select 1 from rdb$database) as id2 from rdb$database; + commit; + + set planonly; + select * from tmp_view tv left join tmp t on t.id=tv.id2; """ act = isql_act('db', test_script) -expected_stdout = """ -PLAN (TV RDB$DATABASE NATURAL) -PLAN (TV RDB$DATABASE NATURAL) -PLAN JOIN (TV RDB$DATABASE NATURAL, T INDEX (PK_TMP_1)) +expected_stdout_5x = """ + PLAN (TV RDB$DATABASE NATURAL) + PLAN (TV RDB$DATABASE NATURAL) + PLAN JOIN (TV RDB$DATABASE NATURAL, T INDEX (PK_TMP_1)) +""" - ID1 ID2 ID -============ ============ ============ - 1 1 +expected_stdout_6x = """ + PLAN ("TV" "SYSTEM"."RDB$DATABASE" NATURAL) + PLAN ("TV" "SYSTEM"."RDB$DATABASE" NATURAL) + PLAN JOIN ("TV" "SYSTEM"."RDB$DATABASE" NATURAL, "T" INDEX ("PUBLIC"."PK_TMP_1")) """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 2670c87030c5a1c620217c20e7db5f13a19aec65 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 00:17:13 +0300 Subject: [PATCH 0900/1064] Added/Updated tests\bugs\core_3537_test.py: minor change; mismatch with expected ratios detected; to be investigated later --- tests/bugs/core_3537_test.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_3537_test.py b/tests/bugs/core_3537_test.py index 21d89384..a7cb9997 100644 --- a/tests/bugs/core_3537_test.py +++ b/tests/bugs/core_3537_test.py @@ -120,17 +120,6 @@ act = python_act('db') -expected_stdout = """ - Check ratio_fetches_to_datapages_for_GTT_DELETE_ROWS: OK - Check ratio_fetches_to_datapages_for_GTT_PRESERVE_ROWS: OK - Check ratio_fetches_to_row_count_for_GTT_DELETE_ROWS: OK - Check ratio_fetches_to_row_count_for_GTT_PRESERVE_ROWS: OK - Check ratio_marks_to_datapages_for_GTT_DELETE_ROWS: OK - Check ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS: OK - Check ratio_marks_to_row_count_for_GTT_DELETE_ROWS: OK - Check ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS: OK -""" - trace = ['log_transactions = true', 'print_perf = true', 'log_initfini = false', @@ -219,6 +208,18 @@ def test_1(act: Action, capsys): if failed_flag: print('Trace for GTT PRESERVE rows: ' + gtt_sav_trace) print('Trace for GTT DELETE rows: ' + gtt_del_trace) + + expected_stdout = """ + Check ratio_fetches_to_datapages_for_GTT_DELETE_ROWS: OK + Check ratio_fetches_to_datapages_for_GTT_PRESERVE_ROWS: OK + Check ratio_fetches_to_row_count_for_GTT_DELETE_ROWS: OK + Check ratio_fetches_to_row_count_for_GTT_PRESERVE_ROWS: OK + Check ratio_marks_to_datapages_for_GTT_DELETE_ROWS: OK + Check ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS: OK + Check ratio_marks_to_row_count_for_GTT_DELETE_ROWS: OK + Check ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS: OK + """ + # Check act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out From f5742a8555e6afdb59f4ad18fe0c96f2db216db7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 13:41:43 +0300 Subject: [PATCH 0901/1064] Updated tests\bugs\core_5020_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_5020_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_5020_test.py b/tests/bugs/core_5020_test.py index 8f1a84fd..c86d30be 100644 --- a/tests/bugs/core_5020_test.py +++ b/tests/bugs/core_5020_test.py @@ -135,11 +135,11 @@ def test_1(act: Action, capsys): expected_stdout_6x = """ Select Expression - ....-> Sort (record length: 36, key length: 16) + ....-> Sort (record length: NN, key length: MM) ........-> Filter - ............-> Table "ZF" Access By ID + ............-> Table "PUBLIC"."ZF" Access By ID ................-> Bitmap - ....................-> Index "FK_ZF__K" Range Scan (full match) + ....................-> Index "PUBLIC"."FK_ZF__K" Range Scan (full match) """ act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 52c843450ece15071b0aaffa71ef1e9ea3e129f7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 13:44:07 +0300 Subject: [PATCH 0902/1064] Added/Updated tests\bugs\core_5049_test.py: Added 'SQL_SCHEMA_PREFIX' - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5049_test.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_5049_test.py b/tests/bugs/core_5049_test.py index eac58c55..8d08aba1 100644 --- a/tests/bugs/core_5049_test.py +++ b/tests/bugs/core_5049_test.py @@ -40,14 +40,16 @@ act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|sqltype).)*$', ''), ('[ \t]+', ' ')]) -expected_stdout = """ - 01: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 UTF8 - 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 UTF8 - 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 UTF8 -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8000 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ae6453b64e30e5193fc987de2b52174b9e11ca4d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 13:46:42 +0300 Subject: [PATCH 0903/1064] Updated tests\bugs\core_5062_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_5062_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_5062_test.py b/tests/bugs/core_5062_test.py index 353d4357..06e1de73 100644 --- a/tests/bugs/core_5062_test.py +++ b/tests/bugs/core_5062_test.py @@ -61,8 +61,11 @@ def test_1(act: Action, capsys): if ps: ps.free() + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TEST_UUID' if act.is_version('<6') else '"TEST_UUID"' + INDEX_NAME = 'TEST_UUID_UNQ' if act.is_version('<6') else '"TEST_UUID_UNQ"' expected_stdout = f""" - PLAN (TEST_UUID INDEX (TEST_UUID_UNQ)) + PLAN ({SQL_SCHEMA_PREFIX}{TABLE_NAME} INDEX ({SQL_SCHEMA_PREFIX}{INDEX_NAME})) 1 """ From 8c892a929e3c0684f4f4c09cebaaa28bec6275d0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 13:50:46 +0300 Subject: [PATCH 0904/1064] Added/Updated tests\bugs\core_5064_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5064_test.py | 92 ++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/tests/bugs/core_5064_test.py b/tests/bugs/core_5064_test.py index 06ca172c..03ed0e75 100644 --- a/tests/bugs/core_5064_test.py +++ b/tests/bugs/core_5064_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5064 FBTEST: bugs.core_5064 +NOTES: + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -35,39 +41,65 @@ """ -act = isql_act('db', test_script) - -expected_stdout = """ - INPUT message field count: 0 - - OUTPUT message field count: 3 - 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: DB_KEY alias: DB_KEY - : table: TEST owner: SYSDBA - 02: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: X alias: X - : table: TEST owner: SYSDBA - 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: Y alias: Y - : table: TEST owner: SYSDBA - - INPUT message field count: 0 - - OUTPUT message field count: 2 - 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: X alias: X - : table: owner: - 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: Y alias: Y - : table: owner: - - X - Y -""" +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + INPUT message field count: 0 + + OUTPUT message field count: 3 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS + : name: DB_KEY alias: DB_KEY + : table: TEST owner: SYSDBA + 02: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS + : name: X alias: X + : table: TEST owner: SYSDBA + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS + : name: Y alias: Y + : table: TEST owner: SYSDBA + + INPUT message field count: 0 + + OUTPUT message field count: 2 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS + : name: X alias: X + : table: owner: + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS + : name: Y alias: Y + : table: owner: + + X + Y + """ + + expected_stdout_6x = """ + INPUT message field count: 0 + OUTPUT message field count: 3 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + : name: DB_KEY alias: DB_KEY + : table: TEST schema: PUBLIC owner: SYSDBA + 02: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + : name: X alias: X + : table: TEST schema: PUBLIC owner: SYSDBA + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + : name: Y alias: Y + : table: TEST schema: PUBLIC owner: SYSDBA + INPUT message field count: 0 + OUTPUT message field count: 2 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + : name: X alias: X + : table: schema: owner: + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + : name: Y alias: Y + : table: schema: owner: + X + Y + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute() assert act.clean_stdout == act.clean_expected_stdout From 9791c88cc9a6382027cf3d759a287a5dfd2bba4f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 13:57:47 +0300 Subject: [PATCH 0905/1064] Added/Updated tests\bugs\core_5070_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5070_test.py | 121 +++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 34 deletions(-) diff --git a/tests/bugs/core_5070_test.py b/tests/bugs/core_5070_test.py index 08023278..383f0f25 100644 --- a/tests/bugs/core_5070_test.py +++ b/tests/bugs/core_5070_test.py @@ -7,14 +7,18 @@ DESCRIPTION: JIRA: CORE-5070 FBTEST: bugs.core_5070 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -db = db_factory() - -test_script = """ +init_script = """ recreate table test1 ( ia integer not null, id integer not null, @@ -22,44 +26,93 @@ dt date not null, constraint test1_pk_ia_id primary key (ia,id) ); +""" - set plan on; - set explain on; +db = db_factory(init = init_script) +substitutions = [] # [('record length.*', ''), ('key length.*', '')] +act = python_act('db', substitutions = substitutions) - select * - from test1 - where - ia=1 and dt='01/01/2015' and it=1 - order by id - ; +#----------------------------------------------------------- +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped - select id - from test1 - where - ia=1 and dt='01/01/2015' and it=1 - group by id - ; +#----------------------------------------------------------- -""" +@pytest.mark.version('>=3.0') +def test_1(act: Action, capsys): + qry_map = { + 1000 : + """ + select * + from test1 + where + ia=1 and dt='01/01/2015' and it=1 + order by id + """ + , + 2000 : + """ + select id + from test1 + where + ia=1 and dt='01/01/2015' and it=1 + group by id + """ + } -act = isql_act('db', test_script) + with act.db.connect() as con: + cur = con.cursor() -expected_stdout = """ - Select Expression - -> Filter - -> Table "TEST1" Access By ID - -> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + for k, v in qry_map.items(): + ps, rs = None, None + try: + ps = cur.prepare(v) - Select Expression - -> Aggregate - -> Filter - -> Table "TEST1" Access By ID - -> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) -""" + print(v) + # Print explained plan with padding eash line by dots in order to see indentations: + 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 rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_stdout_5x = f""" + {qry_map[1000]} + Select Expression + ....-> Filter + ........-> Table "TEST1" Access By ID + ............-> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) -@pytest.mark.version('>=3.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + {qry_map[2000]} + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "TEST1" Access By ID + ................-> Index "TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + """ + + expected_stdout_6x = f""" + {qry_map[1000]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST1" Access By ID + ............-> Index "PUBLIC"."TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + + {qry_map[2000]} + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "PUBLIC"."TEST1" Access By ID + ................-> Index "PUBLIC"."TEST1_PK_IA_ID" Range Scan (partial match: 1/2) + """ + + 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 From 6500245daf165e9c4fecfd047fb1ecb9b034760b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 14:01:09 +0300 Subject: [PATCH 0906/1064] Added/Updated tests\bugs\core_5074_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5074_test.py | 39 ++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_5074_test.py b/tests/bugs/core_5074_test.py index 65b40d6e..f7472a1e 100644 --- a/tests/bugs/core_5074_test.py +++ b/tests/bugs/core_5074_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5074 FBTEST: bugs.core_5074 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,26 +22,33 @@ test_script = """ recreate table test( - a char(10)[0:3] character set octets + array_col char(10)[0:3] character set octets ); set sqlda_display on; - select a[0] from test; + select array_col[0] from test; """ act = isql_act('db', test_script) -expected_stdout = """ - INPUT message field count: 0 - - OUTPUT message field count: 1 - 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 10 charset: 1 OCTETS - : name: A alias: A - : table: TEST owner: SYSDBA -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + expected_stdout_5x = """ + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 10 charset: 1 OCTETS + : name: ARRAY_COL alias: ARRAY_COL + : table: TEST owner: SYSDBA + """ + + expected_stdout_6x = """ + INPUT message field count: 0 + OUTPUT message field count: 1 + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 10 charset: 1 SYSTEM.OCTETS + : name: ARRAY_COL alias: ARRAY_COL + : table: TEST schema: PUBLIC owner: SYSDBA + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output =True) assert act.clean_stdout == act.clean_expected_stdout From 2b9933786f63a7d49013f3e0998658bf1406b8b3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 14:05:37 +0300 Subject: [PATCH 0907/1064] Added/Updated tests\bugs\core_5093_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5093_test.py | 154 ++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 38 deletions(-) diff --git a/tests/bugs/core_5093_test.py b/tests/bugs/core_5093_test.py index 5f50a901..af981b98 100644 --- a/tests/bugs/core_5093_test.py +++ b/tests/bugs/core_5093_test.py @@ -20,6 +20,12 @@ Currently gh-7924 fixed only for FB 6.x, thus charsets for FB 3.x ... 5.x will not be changed. Because of that, expected_output depends on major FB version, see its definition in 'blob_new_cset'. Checked on 6.0.0.223, 5.0.1.1322 + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -90,47 +96,83 @@ select * from t1; """ -expected_stdout_a = """ - 01: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 - : NAME: N0 ALIAS: N0 - 02: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 - : NAME: SI ALIAS: SI - 03: SQLTYPE: 580 INT64 NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 - : NAME: BI ALIAS: BI - 04: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 - : NAME: S2 ALIAS: S2 - 05: SQLTYPE: 480 DOUBLE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 - : NAME: DX ALIAS: DX - 06: SQLTYPE: 482 FLOAT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 - : NAME: FX ALIAS: FX - 07: SQLTYPE: 500 SHORT NULLABLE SCALE: -1 SUBTYPE: 1 LEN: 2 - : NAME: NF ALIAS: NF - 08: SQLTYPE: 570 SQL DATE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 - : NAME: DT ALIAS: DT - 09: SQLTYPE: 560 TIME NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 - : NAME: TM ALIAS: TM - 10: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 - : NAME: C_CHANGE_CB_VALUE ALIAS: C_CHANGE_CB_VALUE - 11: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 - : NAME: C_CHANGE_CHARSET ALIAS: C_CHANGE_CHARSET - 12: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 - : NAME: C_CHANGE_LENGTH ALIAS: C_CHANGE_LENGTH - 13: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 - : NAME: B_CHANGE_CB_VALUE ALIAS: B_CHANGE_CB_VALUE - 14: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 - : NAME: B_CHANGE_CHARSET ALIAS: B_CHANGE_CHARSET - 15: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 - : NAME: B_REMOVE_CHARSET ALIAS: B_REMOVE_CHARSET - 16: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 - : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET -""" - BLOB_NEW_CSET_5X = 'CHARSET: 0 NONE' BLOB_NEW_CSET_6X = 'CHARSET: 4 UTF8' @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout_a + + expected_out_5x_a = """ + 01: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: N0 ALIAS: N0 + 02: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 + : NAME: SI ALIAS: SI + 03: SQLTYPE: 580 INT64 NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: BI ALIAS: BI + 04: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 + : NAME: S2 ALIAS: S2 + 05: SQLTYPE: 480 DOUBLE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: DX ALIAS: DX + 06: SQLTYPE: 482 FLOAT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: FX ALIAS: FX + 07: SQLTYPE: 500 SHORT NULLABLE SCALE: -1 SUBTYPE: 1 LEN: 2 + : NAME: NF ALIAS: NF + 08: SQLTYPE: 570 SQL DATE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: DT ALIAS: DT + 09: SQLTYPE: 560 TIME NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: TM ALIAS: TM + 10: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 + : NAME: C_CHANGE_CB_VALUE ALIAS: C_CHANGE_CB_VALUE + 11: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 + : NAME: C_CHANGE_CHARSET ALIAS: C_CHANGE_CHARSET + 12: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 UTF8 + : NAME: C_CHANGE_LENGTH ALIAS: C_CHANGE_LENGTH + 13: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 + : NAME: B_CHANGE_CB_VALUE ALIAS: B_CHANGE_CB_VALUE + 14: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 + : NAME: B_CHANGE_CHARSET ALIAS: B_CHANGE_CHARSET + 15: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 UTF8 + : NAME: B_REMOVE_CHARSET ALIAS: B_REMOVE_CHARSET + 16: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET + """ + + expected_out_6x_a = """ + 01: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: N0 ALIAS: N0 + 02: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 + : NAME: SI ALIAS: SI + 03: SQLTYPE: 580 INT64 NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: BI ALIAS: BI + 04: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 + : NAME: S2 ALIAS: S2 + 05: SQLTYPE: 480 DOUBLE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: DX ALIAS: DX + 06: SQLTYPE: 482 FLOAT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: FX ALIAS: FX + 07: SQLTYPE: 500 SHORT NULLABLE SCALE: -1 SUBTYPE: 1 LEN: 2 + : NAME: NF ALIAS: NF + 08: SQLTYPE: 570 SQL DATE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: DT ALIAS: DT + 09: SQLTYPE: 560 TIME NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: TM ALIAS: TM + 10: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_CB_VALUE ALIAS: C_CHANGE_CB_VALUE + 11: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_CHARSET ALIAS: C_CHANGE_CHARSET + 12: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_LENGTH ALIAS: C_CHANGE_LENGTH + 13: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_CHANGE_CB_VALUE ALIAS: B_CHANGE_CB_VALUE + 14: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_CHANGE_CHARSET ALIAS: B_CHANGE_CHARSET + 15: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_REMOVE_CHARSET ALIAS: B_REMOVE_CHARSET + 16: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET + """ + + act.expected_stdout = expected_out_5x_a if act.is_version('<6') else expected_out_6x_a act.isql(switches=['-q', '-m'], input='set sqlda_display on; select * from t1;') act.stdout = act.stdout.upper() assert act.clean_stdout == act.clean_expected_stdout @@ -142,7 +184,8 @@ def test_1(act: Action): # blob_new_cset = BLOB_NEW_CSET_5X if act.is_version('<6') else BLOB_NEW_CSET_6X #################################################### - expected_stdout_b = f""" + + expected_out_5x_b = f""" 01: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 : NAME: N0 ALIAS: N0 02: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 @@ -177,7 +220,42 @@ def test_1(act: Action): : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET """ - act.expected_stdout = expected_stdout_b + expected_out_6x_b = f""" + 01: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: N0 ALIAS: N0 + 02: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: SI ALIAS: SI + 03: SQLTYPE: 496 LONG NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: BI ALIAS: BI + 04: SQLTYPE: 500 SHORT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 2 + : NAME: S2 ALIAS: S2 + 05: SQLTYPE: 482 FLOAT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: DX ALIAS: DX + 06: SQLTYPE: 482 FLOAT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: FX ALIAS: FX + 07: SQLTYPE: 580 INT64 NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: NF ALIAS: NF + 08: SQLTYPE: 570 SQL DATE NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 + : NAME: DT ALIAS: DT + 09: SQLTYPE: 510 TIMESTAMP NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: TM ALIAS: TM + 10: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_CB_VALUE ALIAS: C_CHANGE_CB_VALUE + 11: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 4 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_CHARSET ALIAS: C_CHANGE_CHARSET + 12: SQLTYPE: 452 TEXT NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: C_CHANGE_LENGTH ALIAS: C_CHANGE_LENGTH + 13: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_CHANGE_CB_VALUE ALIAS: B_CHANGE_CB_VALUE + 14: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_CHANGE_CHARSET ALIAS: B_CHANGE_CHARSET + 15: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 0 LEN: 8 + : NAME: B_REMOVE_CHARSET ALIAS: B_REMOVE_CHARSET + 16: SQLTYPE: 520 BLOB NULLABLE SCALE: 0 SUBTYPE: 1 LEN: 8 CHARSET: 4 SYSTEM.UTF8 + : NAME: B_ADDED_CHARSET ALIAS: B_ADDED_CHARSET + """ + + act.expected_stdout = expected_out_5x_b if act.is_version('<6') else expected_out_6x_b act.isql(switches=['-q', '-m'], input=sql_script) act.stdout = act.stdout.upper() assert act.clean_stdout == act.clean_expected_stdout From bc836ea7bb572a2c9aadedab494acb2ab4533308 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 14:57:27 +0300 Subject: [PATCH 0908/1064] Added/Updated tests\bugs\core_5118_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5118_test.py | 51 ++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_5118_test.py b/tests/bugs/core_5118_test.py index 9931b9cd..92ce523c 100644 --- a/tests/bugs/core_5118_test.py +++ b/tests/bugs/core_5118_test.py @@ -14,10 +14,14 @@ This is because of optimizer changed in 5.x and issues plan with only *one* occurrence of 'INDEX' for such cases. See: https://github.com/FirebirdSQL/firebird/pull/7707 - "Better processing and optimization if IN ". Commit: https://github.com/FirebirdSQL/firebird/commit/0493422c9f729e27be0112ab60f77e753fabcb5b, 04-sep-2023. - Requested by dimitr, letters with subj 'core_5118_test', since 11.09.2024 17:26. - Checked on 6.0.0.452, 5.0.2.1493, 4.0.5.3136, 3.0.13.33789. + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -47,20 +51,6 @@ act = python_act('db', substitutions = [ ('[ \t]+',' ') ]) -expected_stdout = """ - PLAN (TEST INDEX (TEST_CONCAT_TEXT)) - CONCAT_TEXT nom1 prenom1 - Records affected: 1 - - PLAN (TEST INDEX (TEST_CONCAT_TEXT)) - CONCAT_TEXT nom2 prenom2 - Records affected: 1 - - PLAN (TEST INDEX (TEST_CONCAT_TEXT)) - CONCAT_TEXT nom3 prenom3 - Records affected: 1 -""" - test_sql = """ set list on; set plan on; @@ -77,6 +67,33 @@ def test_1(act: Action): srv.database.local_backup(database = act.db.db_path, backup_stream = backup) backup.seek(0) srv.database.local_restore(database = act.db.db_path, backup_stream=backup, flags = SrvRestoreFlag.REPLACE) - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom1 prenom1 + Records affected: 1 + + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom2 prenom2 + Records affected: 1 + + PLAN (TEST INDEX (TEST_CONCAT_TEXT)) + CONCAT_TEXT nom3 prenom3 + Records affected: 1 + """ + + expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_CONCAT_TEXT")) + CONCAT_TEXT nom1 prenom1 + Records affected: 1 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_CONCAT_TEXT")) + CONCAT_TEXT nom2 prenom2 + Records affected: 1 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_CONCAT_TEXT")) + CONCAT_TEXT nom3 prenom3 + Records affected: 1 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=['-q'], input = test_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ddedf3a3b7bbdb2b0ca1ea45592ae857fb501bbf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:00:02 +0300 Subject: [PATCH 0909/1064] Added/Updated tests\bugs\core_5122_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5122_test.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_5122_test.py b/tests/bugs/core_5122_test.py index 2a7caf07..fc7b23f2 100644 --- a/tests/bugs/core_5122_test.py +++ b/tests/bugs/core_5122_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5122 FBTEST: bugs.core_5122 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,8 +22,9 @@ act = python_act('db') -expected_stdout = """ - PLAN (TEST INDEX (TEST_CALC_S)) +test_sql= """ + set planonly; + select * from test where 'zxc' || s starting with 'qwe'; """ @pytest.mark.version('>=3') @@ -27,8 +34,15 @@ def test_1(act: Action): cur1.execute("recreate table test(s varchar(10))") cur1.execute("create index test_calc_s on test computed by ('zxc' || s)") con1.commit() - # - act.expected_stdout = expected_stdout - act.isql(switches=['-n'], - input="set planonly; select * from test where 'zxc' || s starting with 'qwe';") + + expected_stdout_5x = """ + PLAN (TEST INDEX (TEST_CALC_S)) + """ + expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_CALC_S")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + + act.isql(switches=['-q', '-n'], input = test_sql) assert act.clean_stdout == act.clean_expected_stdout From 2ccac069046f1806af20b0c0723f32b5abca39d4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:03:27 +0300 Subject: [PATCH 0910/1064] Added/Updated tests\bugs\core_5130_test.py: Added 'SQL_SCHEMA_PREFIX' - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5130_test.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_5130_test.py b/tests/bugs/core_5130_test.py index 5c1f6be2..e6fb0c7e 100644 --- a/tests/bugs/core_5130_test.py +++ b/tests/bugs/core_5130_test.py @@ -8,6 +8,10 @@ DESCRIPTION: JIRA: CORE-5130 FBTEST: bugs.core_5130 +NOTES: + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,17 +35,19 @@ act = isql_act('db', test_script) -expected_stderr = """ - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -ALTER VIEW V1 failed - -Dynamic SQL Error - -SQL error code = -607 - -No subqueries permitted for VIEW WITH CHECK OPTION -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + VIEW_NAME = 'V1' if act.is_version('<6') else '"V1"' + expected_stdout = f""" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER VIEW {SQL_SCHEMA_PREFIX}{VIEW_NAME} failed + -Dynamic SQL Error + -SQL error code = -607 + -No subqueries permitted for VIEW WITH CHECK OPTION + """ + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f44e3c4bfc19ff0fb712f4102934a9cf806998b6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:06:14 +0300 Subject: [PATCH 0911/1064] Added/Updated tests\bugs\core_5146_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5146_test.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_5146_test.py b/tests/bugs/core_5146_test.py index 56e807ff..ad71012c 100644 --- a/tests/bugs/core_5146_test.py +++ b/tests/bugs/core_5146_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5146 FBTEST: bugs.core_5146 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -36,13 +42,17 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN JOIN (HI INDEX (HI_PROJID), HE INDEX (HE_ITEMID)) -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + + expected_stdout_5x = """ + PLAN JOIN (HI INDEX (HI_PROJID), HE INDEX (HE_ITEMID)) + """ + expected_stdout_6x = """ + PLAN JOIN ("HI" INDEX ("PUBLIC"."HI_PROJID"), "HE" INDEX ("PUBLIC"."HE_ITEMID")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 0369db531091c2ad8bc5d94e6da5015e19c15e05 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:09:38 +0300 Subject: [PATCH 0912/1064] Added/Updated tests\bugs\core_5161_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5161_test.py | 48 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_5161_test.py b/tests/bugs/core_5161_test.py index 7477eadb..a8c9e50c 100644 --- a/tests/bugs/core_5161_test.py +++ b/tests/bugs/core_5161_test.py @@ -5,8 +5,16 @@ ISSUE: 5444 TITLE: Unique index could be created on non-unique data DESCRIPTION: + Confirmed on: WI-V3.0.0.32378, WI-V2.5.6.26980: + one might to create unique index when number of inserted rows was >= 3276. JIRA: CORE-5161 FBTEST: bugs.core_5161 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -15,9 +23,8 @@ db = db_factory() test_script = """ - -- Confirmed on: WI-V3.0.0.32378, WI-V2.5.6.26980: - -- one might to create unique index when number of inserted rows was >= 3276. + set list on; recreate table t (id int, x int); set term ^; execute block as @@ -32,13 +39,8 @@ end ^ set term ;^ - - set list on; - select sign(count(*)) as cnt_non_zero from t; - set echo on; - insert into t values(1, -999999999); commit; @@ -48,15 +50,14 @@ select id, x from t where id = 1; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ CNT_NON_ZERO 1 - insert into t values(1, -999999999); - commit; - create unique index t_id_unique on t(id); - set plan on; - select id, x from t where id = 1; + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index "T_ID_UNIQUE" + -Problematic key value is ("ID" = 1) PLAN (T NATURAL) ID 1 X -888888888 @@ -64,17 +65,20 @@ X -999999999 """ -expected_stderr = """ +expected_stdout_6x = """ + CNT_NON_ZERO 1 Statement failed, SQLSTATE = 23000 - attempt to store duplicate value (visible to active transactions) in unique index "T_ID_UNIQUE" + attempt to store duplicate value (visible to active transactions) in unique index "PUBLIC"."T_ID_UNIQUE" -Problematic key value is ("ID" = 1) + PLAN ("PUBLIC"."T" NATURAL) + ID 1 + X -888888888 + ID 1 + X -999999999 """ @pytest.mark.version('>=2.5.6') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e4e5fc9d5b21a4b76e913a7ec4e4eeb28431e52c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:13:14 +0300 Subject: [PATCH 0913/1064] Added/Updated tests\bugs\core_5166_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5166_test.py | 88 ++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/tests/bugs/core_5166_test.py b/tests/bugs/core_5166_test.py index 8d749239..247da651 100644 --- a/tests/bugs/core_5166_test.py +++ b/tests/bugs/core_5166_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5166 FBTEST: bugs.core_5166 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,40 +57,56 @@ update test2 set u=true, v=null, w=true where coalesce(u,v,w) is null rows 1; """ -act = isql_act('db', test_script) - -expected_stdout = """ - X - Records affected: 0 - Records affected: 1 - Records affected: 1 - Records affected: 1 - Records affected: 1 - Records affected: 1 - Records affected: 1 - Records affected: 0 - Records affected: 0 -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST1_X_UNQ" on table "TEST1" - -Problematic key value is ("X" = TRUE) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "TEST2" - -Problematic key value is ("U" = TRUE, "V" = TRUE, "W" = TRUE) - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "TEST2" - -Problematic key value is ("U" = TRUE, "V" = NULL, "W" = TRUE) -""" +substitutions = [] # [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + expected_stdout_5x = """ + X + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST1_X_UNQ" on table "TEST1" + -Problematic key value is ("X" = TRUE) + Records affected: 0 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "TEST2" + -Problematic key value is ("U" = TRUE, "V" = TRUE, "W" = TRUE) + Records affected: 0 + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "TEST2" + -Problematic key value is ("U" = TRUE, "V" = NULL, "W" = TRUE) + Records affected: 0 + """ + + expected_stdout_6x = """ + X + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST1_X_UNQ" on table "PUBLIC"."TEST1" + -Problematic key value is ("X" = TRUE) + Records affected: 0 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Records affected: 1 + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "PUBLIC"."TEST2" + -Problematic key value is ("U" = TRUE, "V" = TRUE, "W" = TRUE) + Records affected: 0 + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST2_UVW_UNQ" on table "PUBLIC"."TEST2" + -Problematic key value is ("U" = TRUE, "V" = NULL, "W" = TRUE) + Records affected: 0 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From e7393a1957678ac225c485d172af743600994222 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:19:34 +0300 Subject: [PATCH 0914/1064] Added/Updated tests\bugs\core_5194_test.py: minor changes --- tests/bugs/core_5194_test.py | 42 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_5194_test.py b/tests/bugs/core_5194_test.py index a933ed23..79abc5a0 100644 --- a/tests/bugs/core_5194_test.py +++ b/tests/bugs/core_5194_test.py @@ -5,10 +5,10 @@ ISSUE: 5475 TITLE: Invalid computed by definition generated by isql -x DESCRIPTION: - We create table and then run ISQL with '-x' key and saving its output to file. - This operation should NOT produce any error (see var. 'f_xmeta_err'). - Then we drop table and run ISQL again but for APPLYING extracted metadata. - If "ISQL -x" will produce script with invalid syntax, compiler will raise error. + We create table and then run ISQL with '-x' key and saving its output to file. + This operation should NOT produce any error (see var. 'f_xmeta_err'). + Then we drop table and run ISQL again but for APPLYING extracted metadata. + If "ISQL -x" will produce script with invalid syntax, compiler will raise error. JIRA: CORE-5194 FBTEST: bugs.core_5194 """ @@ -26,6 +26,7 @@ test_script = """ set list on; + -- instead of 'show tab': select rf.rdb$field_name ,ff.rdb$field_length @@ -38,19 +39,6 @@ order by rdb$field_name; """ -expected_stdout = """ - RDB$FIELD_NAME A - RDB$FIELD_LENGTH 8 - RDB$FIELD_SCALE 0 - RDB$FIELD_TYPE 35 - RDB$COMPUTED_SOURCE - RDB$FIELD_NAME B - RDB$FIELD_LENGTH 8 - RDB$FIELD_SCALE -9 - RDB$FIELD_TYPE 16 - RDB$COMPUTED_SOURCE (current_timestamp - a) -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): act.isql(switches=['-x']) @@ -62,10 +50,24 @@ def test_1(act: Action): att1.commit() # act.reset() - act.isql(switches=[], input=init_meta) + act.isql(switches = ['-q'], input = init_meta) assert act.clean_stdout == '' - # This should issue DDL of table TEST which was just created by extracted metadata: act.reset() + + expected_stdout = """ + RDB$FIELD_NAME A + RDB$FIELD_LENGTH 8 + RDB$FIELD_SCALE 0 + RDB$FIELD_TYPE 35 + RDB$COMPUTED_SOURCE + RDB$FIELD_NAME B + RDB$FIELD_LENGTH 8 + RDB$FIELD_SCALE -9 + RDB$FIELD_TYPE 16 + RDB$COMPUTED_SOURCE (current_timestamp - a) + """ + + # This should issue DDL of table TEST which was just created by extracted metadata: act.expected_stdout = expected_stdout - act.isql(switches=['-q'], input= test_script) + act.isql(switches=['-q'], input= test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From aad7f0ed56db875bcbe4493c0b6e7ec0020924ea Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:34:31 +0300 Subject: [PATCH 0915/1064] fixed wrong regexp: removed duplicated `+` which caused tests fail in Python 3.8 (but worked fine on 3.12). Noted by Anton Zuev, RedSoft. --- tests/bugs/core_0058_test.py | 2 +- tests/bugs/core_0059_test.py | 2 +- tests/bugs/core_0070_test.py | 2 +- tests/bugs/core_0104_test.py | 2 +- tests/bugs/core_0115_test.py | 2 +- tests/bugs/core_0116_test.py | 2 +- tests/bugs/core_0166_test.py | 2 +- tests/bugs/core_0196_test.py | 2 +- tests/bugs/core_0209_test.py | 2 +- tests/bugs/core_0223_test.py | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_0058_test.py b/tests/bugs/core_0058_test.py index f4dbe7e8..878353e9 100644 --- a/tests/bugs/core_0058_test.py +++ b/tests/bugs/core_0058_test.py @@ -67,7 +67,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0059_test.py b/tests/bugs/core_0059_test.py index 37cd12c3..c90bb922 100644 --- a/tests/bugs/core_0059_test.py +++ b/tests/bugs/core_0059_test.py @@ -36,7 +36,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0070_test.py b/tests/bugs/core_0070_test.py index 409e9dfc..0ddd9651 100644 --- a/tests/bugs/core_0070_test.py +++ b/tests/bugs/core_0070_test.py @@ -39,7 +39,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0104_test.py b/tests/bugs/core_0104_test.py index b267aec3..7c54a729 100644 --- a/tests/bugs/core_0104_test.py +++ b/tests/bugs/core_0104_test.py @@ -44,7 +44,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', ''), ('INTEG_\\d+', 'INTEG') ] +substitutions = [ ('line: \\d+, col: \\d+', ''), ('INTEG_\\d+', 'INTEG') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0115_test.py b/tests/bugs/core_0115_test.py index 7b4248f2..a7b55895 100644 --- a/tests/bugs/core_0115_test.py +++ b/tests/bugs/core_0115_test.py @@ -53,7 +53,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0116_test.py b/tests/bugs/core_0116_test.py index 936498ad..9232b4e1 100644 --- a/tests/bugs/core_0116_test.py +++ b/tests/bugs/core_0116_test.py @@ -35,7 +35,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0166_test.py b/tests/bugs/core_0166_test.py index 68cc154a..76263f5c 100644 --- a/tests/bugs/core_0166_test.py +++ b/tests/bugs/core_0166_test.py @@ -71,7 +71,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0196_test.py b/tests/bugs/core_0196_test.py index 9f8aa390..84cb60f0 100644 --- a/tests/bugs/core_0196_test.py +++ b/tests/bugs/core_0196_test.py @@ -38,7 +38,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0209_test.py b/tests/bugs/core_0209_test.py index cbd7ac9e..622b848e 100644 --- a/tests/bugs/core_0209_test.py +++ b/tests/bugs/core_0209_test.py @@ -81,7 +81,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) diff --git a/tests/bugs/core_0223_test.py b/tests/bugs/core_0223_test.py index e26d62b0..f136a45b 100644 --- a/tests/bugs/core_0223_test.py +++ b/tests/bugs/core_0223_test.py @@ -51,7 +51,7 @@ addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] addi_subst_tokens = addi_subst_settings['addi_subst'] -substitutions = [ ('line: \\d+, col: \\d++', '') ] +substitutions = [ ('line: \\d+, col: \\d+', '') ] for p in addi_subst_tokens.split(' '): substitutions.append( (p, '') ) From b8ea8b9e879bfacc6034a567b0b74df4a666aa7c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:39:37 +0300 Subject: [PATCH 0916/1064] Added/Updated tests\bugs\core_5201_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5201_test.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_5201_test.py b/tests/bugs/core_5201_test.py index dbf8af94..daee085e 100644 --- a/tests/bugs/core_5201_test.py +++ b/tests/bugs/core_5201_test.py @@ -23,6 +23,12 @@ gbak: ERROR:Database is not online due to failure to activate one or more indices. gbak: ERROR: Run gfix -online to bring database online without active indices. (actual since 5.0.0.932; will be soon also for FB 3.x and 4.x - see letter from Alex, 07.02.2023 11:53). + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -47,23 +53,33 @@ act = python_act('db') -gbak_expected_stdout = """ - gbak: ERROR:attempt to store duplicate value (visible to active transactions) in unique index "TEST_1_UNQ" - gbak: ERROR: Problematic key value is ( = 1) - gbak: ERROR:Database is not online due to failure to activate one or more indices. - gbak: ERROR: Run gfix -online to bring database online without active indices. -""" - fbk_file = temp_file('core_5201.fbk') tmp_db_file = temp_file('tmp_core_5201.fdb') @pytest.mark.version('>=3.0') def test_1(act: Action, fbk_file: Path, tmp_db_file: Path): + with act.connect_server() as srv: srv.database.backup(database=act.db.db_path, backup=fbk_file) assert srv.readlines() == [] # - act.expected_stdout = gbak_expected_stdout + + gbak_expected_out_5x = """ + gbak: ERROR:attempt to store duplicate value (visible to active transactions) in unique index "TEST_1_UNQ" + gbak: ERROR: Problematic key value is ( = 1) + gbak: ERROR:Database is not online due to failure to activate one or more indices. + gbak: ERROR: Run gfix -online to bring database online without active indices. + """ + + gbak_expected_out_6x = """ + gbak: ERROR:attempt to store duplicate value (visible to active transactions) in unique index "PUBLIC"."TEST_1_UNQ" + gbak: ERROR: Problematic key value is ( = 1) + gbak: ERROR:Database is not online due to failure to activate one or more indices. + gbak: ERROR: Run gfix -online to bring database online without active indices. + """ + + act.expected_stdout = gbak_expected_out_5x if act.is_version('<6') else gbak_expected_out_6x + act.gbak(switches=['-rep', '-v', str(fbk_file), str(tmp_db_file)], combine_output = True) p_gbak_err = re.compile('^gbak:\s?ERROR:', re.IGNORECASE) From e356356d79188c2e69468263f2f54ad0347a0cce Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:47:25 +0300 Subject: [PATCH 0917/1064] Added/Updated tests\bugs\core_5207_test.py: Added check to return_code for proper check outcome of extracting and applying metadata. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5207_test.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5207_test.py b/tests/bugs/core_5207_test.py index a612a026..afbc1ad3 100644 --- a/tests/bugs/core_5207_test.py +++ b/tests/bugs/core_5207_test.py @@ -11,6 +11,10 @@ Afterall, we try to apply extracted metadata to temp database (that was created auto by fbtest). JIRA: CORE-5207 FBTEST: bugs.core_5207 +NOTES: + [01.07.2025] pzotov + Added check to return_code for proper check outcome of extracting and applying metadata. + Checked on 6.0.0.884 (SS/CS); 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -32,13 +36,18 @@ def test_1(act: Action, fbk_file: Path, fdb_file: Path, capsys): with act.connect_server() as srv: srv.database.restore(database=fdb_file, backup=fbk_file) srv.wait() - act.isql(switches=['-x', str(fdb_file)], connect_db=False) + # ------------------------------------------- + act.isql(switches=['-x', str(fdb_file)], connect_db = False) + assert act.return_code == 0, f'Attempt to extract metadata failed:\n{act.clean_stdout}' metadata = act.stdout + act.reset() + # ------------------------------------------- # Check metadata for line in metadata.splitlines(): if 'GRANT USAGE ON DOMAIN' in line: pytest.fail(f'WRONG GRANT: {line}') + # ------------------------------------------- # Apply metadata to main test database - act.reset() - act.isql(switches=[], input=metadata) - assert act.clean_stdout == act.clean_expected_stdout + act.xpected_stdout = '' + act.isql(switches = ['-q'], input = metadata, combine_output = True) + assert act.return_code == 0, f'Attempt to apply metadata failed:\n{act.clean_stdout}' From b7bc66b0ad44b2fa45bcfcf6dbd9e65fc308186a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 15:59:31 +0300 Subject: [PATCH 0918/1064] Added/Updated tests\bugs\core_5216_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5216_test.py | 185 ++++++++++++++++++++++------------- 1 file changed, 118 insertions(+), 67 deletions(-) diff --git a/tests/bugs/core_5216_test.py b/tests/bugs/core_5216_test.py index 79b3f384..3af2d721 100644 --- a/tests/bugs/core_5216_test.py +++ b/tests/bugs/core_5216_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5216 FBTEST: bugs.core_5216 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -19,8 +25,8 @@ db = db_factory() test_script = """ - recreate exception rio 'Exception w/o parameter test. Invalid value detected'; - recreate exception foo 'Exception with parameter test. Invalid value of BAR = @1'; + recreate exception exc_no_param 'Exception w/o parameter test. Invalid value detected'; + recreate exception exc_with_param 'Exception with parameter test. Invalid value: @1'; recreate table test(id int constraint test_pk primary key using index test_pk, x int not null, y int not null); commit; insert into test(id, x, y) values(1, 100, 200); @@ -165,7 +171,7 @@ x = x * 100; when any do begin - exception rio; + exception exc_no_param; end end '''' into x; end @@ -177,7 +183,7 @@ ^ -- -FOO - -- -Exception with parameter test. Invalid value of BAR = *** null *** + -- -Exception with parameter test. Invalid value: *** null *** execute block as begin execute statement @@ -198,7 +204,7 @@ x = 99999; when any do begin - exception foo using(:x); + exception exc_with_param using(:x); end end '''' @@ -215,68 +221,113 @@ act = isql_act('db', test_script, substitutions=substitutions) -expected_stderr = """ - Statement failed, SQLSTATE = 42S22 - Dynamic SQL Error - -SQL error code = -206 - -Column unknown - -NON_EXISTING_COLUMN - -At line 1, column 8 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = 22012 - arithmetic exception, numeric overflow, or string truncation - -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - -At block line: 1, col: 37 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = 42000 - validation error for variable R, value "*** null ***" - -At block line: 5, col: 17 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = 23000 - validation error for column "TEST"."X", value "*** null ***" - -At block line: 4, col: 25 - -At block line: 5, col: 17 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = 23000 - validation error for column "TEST"."Y", value "*** null ***" - -At block line: 5, col: 25 - -At block line: 5, col: 17 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "TEST" - -Problematic key value is ("ID" = 1) - -At block line: 4, col: 33 - -At block line: 5, col: 25 - -At block line: 5, col: 17 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = HY000 - exception 55 - -RIO - -Exception w/o parameter test. Invalid value detected - -At block line: 8, col: 33 - -At block line: 4, col: 27 - -At block line: 5, col: 17 - -At block line: 3, col: 9 - - Statement failed, SQLSTATE = HY000 - exception 56 - -FOO - -Exception with parameter test. Invalid value of BAR = *** null *** - -At block line: 8, col: 41 - -At block line: 5, col: 29 - -At block line: 5, col: 17 - -At block line: 3, col: 9 -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + expected_stdout_5x = f""" + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -NON_EXISTING_COLUMN + -At line N, column M + At block line: N, col: M + Statement failed, SQLSTATE = 22012 + arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 42000 + validation error for variable R, value "*** null ***" + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."X", value "*** null ***" + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + validation error for column "TEST"."Y", value "*** null ***" + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "TEST" + -Problematic key value is ("ID" = 1) + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = HY000 + exception K + -EXC_NO_PARAM + -Exception w/o parameter test. Invalid value detected + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = HY000 + exception K + -EXC_WITH_PARAM + -Exception with parameter test. Invalid value: *** null *** + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + """ + + expected_stdout_6x = f""" + Statement failed, SQLSTATE = 42S22 + Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -"NON_EXISTING_COLUMN" + -At line N, column M + At block line: N, col: M + Statement failed, SQLSTATE = 22012 + arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 42000 + validation error for variable "R", value "*** null ***" + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."X", value "*** null ***" + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST"."Y", value "*** null ***" + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "PUBLIC"."TEST" + -Problematic key value is ("ID" = 1) + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = HY000 + exception K + -"PUBLIC"."EXC_NO_PARAM" + -Exception w/o parameter test. Invalid value detected + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + Statement failed, SQLSTATE = HY000 + exception K + -"PUBLIC"."EXC_WITH_PARAM" + -Exception with parameter test. Invalid value: *** null *** + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + At block line: N, col: M + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 77dbc54811a55d0eabb6636583060175ef009ebf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 16:05:56 +0300 Subject: [PATCH 0919/1064] Added/Updated tests\bugs\core_5218_test.py: Added 'SQL_SCHEMA_PREFIX' - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5218_test.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_5218_test.py b/tests/bugs/core_5218_test.py index 52e04115..7dcac782 100644 --- a/tests/bugs/core_5218_test.py +++ b/tests/bugs/core_5218_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-5218 FBTEST: bugs.core_5218 +NOTES: + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -31,21 +35,26 @@ act = python_act('db') -expected_stdout = """ - CREATE TABLE TEST (F01 INTEGER CONSTRAINT F01_NN NOT NULL, - F02 INTEGER CONSTRAINT F02_NN NOT NULL, - F03 INTEGER CONSTRAINT F03_NN NOT NULL, - CONSTRAINT F01_PK PRIMARY KEY (F01), - CONSTRAINT F02_UK UNIQUE (F02)); - ALTER TABLE TEST ADD CONSTRAINT F03_FK FOREIGN KEY (F03) REFERENCES TEST (F01); -""" @pytest.mark.version('>=2.5.6') def test_1(act: Action): - act.expected_stdout = expected_stdout act.isql(switches=['-x']) - # filter stdout + assert act.return_code == 0, f'Attempt to extract metadata failed:\n{act.clean_stdout}' act.stdout = '\n'.join([line for line in act.stdout.splitlines() if 'CONSTRAINT' in line]) + + # ----------------------------------- + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + CREATE TABLE {SQL_SCHEMA_PREFIX}TEST (F01 INTEGER CONSTRAINT F01_NN NOT NULL, + F02 INTEGER CONSTRAINT F02_NN NOT NULL, + F03 INTEGER CONSTRAINT F03_NN NOT NULL, + CONSTRAINT F01_PK PRIMARY KEY (F01), + CONSTRAINT F02_UK UNIQUE (F02)); + ALTER TABLE {SQL_SCHEMA_PREFIX}TEST ADD CONSTRAINT F03_FK FOREIGN KEY (F03) REFERENCES {SQL_SCHEMA_PREFIX}TEST (F01); + """ + + act.expected_stdout = expected_stdout + # filter stdout assert act.clean_stdout == act.clean_expected_stdout From b2ecd9a96e2e9264229a9f222a9d65353f57792a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 16:09:39 +0300 Subject: [PATCH 0920/1064] Added/Updated tests\bugs\core_5248_test.py: Added f-notation into expected_* in order to make proper content in FB 6.x (role name is enclosed in quotes there). Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5248_test.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_5248_test.py b/tests/bugs/core_5248_test.py index 4923d1a2..b2bb7e51 100644 --- a/tests/bugs/core_5248_test.py +++ b/tests/bugs/core_5248_test.py @@ -11,8 +11,11 @@ 2. Commented out (and will be deleted later) code that expected error when user who was granted role with admin option tries to revoke this role from himself. Seince fixed GH-8462 this is NOT so. 3. Replaced hard-coded names/passwords with variables that are provided by fixtures (tmp_usr*, tmp_role*). - Checked on 6.0.0.660; 5.0.3.1624; 4.0.6.3189. + + [01.07.2025] pzotov + Added f-notation into expected_* in order to make proper content in FB 6.x (role name is enclosed in quotes there). + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214. """ import locale @@ -180,7 +183,8 @@ def test_2(act: Action, tmp_usr0: User, tmp_usr1: User, tmp_usr2: User, tmp_usr3 """ - act.expected_stdout = """ + ROLE_NAME = 'TMP_ROLE1' if act.is_version('<6') else '"TMP_ROLE1"' + act.expected_stdout = f""" MSG Point-1 WHO_AM_I SYSDBA WHO_WAS_GRANTED TMP$C5248_USR1 @@ -246,7 +250,7 @@ def test_2(act: Action, tmp_usr0: User, tmp_usr1: User, tmp_usr2: User, tmp_usr3 Statement failed, SQLSTATE = 28000 unsuccessful metadata update -DROP ROLE TMP_ROLE1 failed - -no permission for DROP access to ROLE TMP_ROLE1 + -no permission for DROP access to ROLE {ROLE_NAME} COUNT 1 MSG Point-6 WHO_AM_I TMP$C5248_USR0 From 138619ebe38e6eb4d565d329d8e9bd996a21d1a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 16:16:53 +0300 Subject: [PATCH 0921/1064] Added/Updated tests\bugs\core_5275_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5275_test.py | 82 ++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/tests/bugs/core_5275_test.py b/tests/bugs/core_5275_test.py index 5969ad03..e0d4e11f 100644 --- a/tests/bugs/core_5275_test.py +++ b/tests/bugs/core_5275_test.py @@ -27,7 +27,6 @@ gen_id(,1) will return 0 (ZERO!) rather than 1. See also CORE-6084 and its fix: https://github.com/FirebirdSQL/firebird/commit/23dc0c6297825b2e9006f4d5a2c488702091033d This is considered as *expected* and is noted in doc/README.incompatibilities.3to4.txt - Because of this, it was decided to replace 'alter sequence restart...' with subtraction of two gen values: c = gen_id(, -gen_id(, 0)) -- see procedure sp_restart_sequences. [15.09.2022] pzotov @@ -42,14 +41,18 @@ This test FAILS on Linux when running against FB 4.x (almost every run on Classic, but also it can fail on Super). Connection that is waiting for COMMIT during index creation for some reason can finish its work successfully, despite the fact that we issue 'delete from mon$attachments' and all transactions have to be rolled back. - Issue that was described in the ticket can be reproduced if attachment will be killed during creation of SECOND (non-computed) index for big table within the same transaction that creates first (computed-by) index. Perhaps, one need to query IndexRoot Page in some other ('monitoring') connection and run 'delete from mon$attachments' command exactly at the moment when result of parsing shows that we have only 1st index for selected relation. Discussed with dimitr et al, letters ~20-mar-2023. - Test needs to be fully re-implemented, but it remains avaliable for Windows because it shows stable results there. + + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import platform @@ -197,40 +200,6 @@ delete from mon$attachments where mon$attachment_id<>current_connection; """ -expected_stdout = """ - 0: BULK INSERTS LOG: BULK_INSERT_START - 0: BULK INSERTS LOG: STATEMENT FAILED, SQLSTATE = 08003 - 0: BULK INSERTS LOG: CONNECTION SHUTDOWN - 0: BULK INSERTS LOG: AFTER LINE - 0: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING - 0: CREATE INDEX LOG: CREATE_INDX_START - 0: CREATE INDEX LOG: SET TRANSACTION WAIT; - 0: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY('WAIT' || S); - 0: CREATE INDEX LOG: SET ECHO OFF; - 0: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 08003 - 0: CREATE INDEX LOG: CONNECTION SHUTDOWN - 0: CREATE INDEX LOG: AFTER LINE - 0: KILL ATTACH LOG: RECORDS AFFECTED: - 1: BULK INSERTS LOG: BULK_INSERT_START - 1: BULK INSERTS LOG: STATEMENT FAILED, SQLSTATE = 08003 - 1: BULK INSERTS LOG: CONNECTION SHUTDOWN - 1: BULK INSERTS LOG: AFTER LINE - 1: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING - 1: CREATE INDEX LOG: CREATE_INDX_START - 1: CREATE INDEX LOG: SET TRANSACTION WAIT; - 1: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY('WAIT' || S); - 1: CREATE INDEX LOG: SET ECHO OFF; - 1: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 08003 - 1: CREATE INDEX LOG: CONNECTION SHUTDOWN - 1: CREATE INDEX LOG: AFTER LINE - 1: KILL ATTACH LOG: RECORDS AFFECTED: - VALIDATION STDOUT: 20:05:26.86 VALIDATION STARTED - VALIDATION STDOUT: 20:05:26.86 RELATION 128 (TEST) - VALIDATION STDOUT: 20:05:26.86 PROCESS POINTER PAGE 0 OF 1 - VALIDATION STDOUT: 20:05:26.86 INDEX 1 (TEST_X) - VALIDATION STDOUT: 20:05:26.86 RELATION 128 (TEST) IS OK - VALIDATION STDOUT: 20:05:26.86 VALIDATION FINISHED -""" def print_validation(line: str) -> None: if line.strip(): @@ -287,6 +256,45 @@ def test_1(act: Action, bulk_insert_script: Path, bulk_insert_output: Path, with act.connect_server() as srv: srv.database.validate(database=act.db.db_path, callback=print_validation) + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TEST' if act.is_version('<6') else '"TEST"' + INDEX_NAME = 'TEST_X' if act.is_version('<6') else '"TEST_X"' + + expected_stdout = f""" + 0: BULK INSERTS LOG: BULK_INSERT_START + 0: BULK INSERTS LOG: STATEMENT FAILED, SQLSTATE = 08003 + 0: BULK INSERTS LOG: CONNECTION SHUTDOWN + 0: BULK INSERTS LOG: AFTER LINE + 0: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING + 0: CREATE INDEX LOG: CREATE_INDX_START + 0: CREATE INDEX LOG: SET TRANSACTION WAIT; + 0: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY('WAIT' || S); + 0: CREATE INDEX LOG: SET ECHO OFF; + 0: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 08003 + 0: CREATE INDEX LOG: CONNECTION SHUTDOWN + 0: CREATE INDEX LOG: AFTER LINE + 0: KILL ATTACH LOG: RECORDS AFFECTED: + 1: BULK INSERTS LOG: BULK_INSERT_START + 1: BULK INSERTS LOG: STATEMENT FAILED, SQLSTATE = 08003 + 1: BULK INSERTS LOG: CONNECTION SHUTDOWN + 1: BULK INSERTS LOG: AFTER LINE + 1: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING + 1: CREATE INDEX LOG: CREATE_INDX_START + 1: CREATE INDEX LOG: SET TRANSACTION WAIT; + 1: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY('WAIT' || S); + 1: CREATE INDEX LOG: SET ECHO OFF; + 1: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 08003 + 1: CREATE INDEX LOG: CONNECTION SHUTDOWN + 1: CREATE INDEX LOG: AFTER LINE + 1: KILL ATTACH LOG: RECORDS AFFECTED: + VALIDATION STDOUT: 20:05:26.86 VALIDATION STARTED + VALIDATION STDOUT: 20:05:26.86 RELATION 128 ({SQL_SCHEMA_PREFIX}{TABLE_NAME}) + VALIDATION STDOUT: 20:05:26.86 PROCESS POINTER PAGE 0 OF 1 + VALIDATION STDOUT: 20:05:26.86 INDEX 1 ({SQL_SCHEMA_PREFIX}{INDEX_NAME}) + VALIDATION STDOUT: 20:05:26.86 RELATION 128 ({SQL_SCHEMA_PREFIX}{TABLE_NAME}) IS OK + VALIDATION STDOUT: 20:05:26.86 VALIDATION FINISHED + """ + # Check act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out From 619ceaefb66a8ecd09d23ba3b8f7229c4239dd13 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 20:37:44 +0300 Subject: [PATCH 0922/1064] Added/Updated tests\bugs\core_5313_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5313_test.py | 47 ++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/tests/bugs/core_5313_test.py b/tests/bugs/core_5313_test.py index e7c08387..ca8f4cb4 100644 --- a/tests/bugs/core_5313_test.py +++ b/tests/bugs/core_5313_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5313 FBTEST: bugs.core_5313 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -17,38 +23,37 @@ test_script = """ set planonly; set sqlda_display on; - select list(trim(rdb$relation_name), ?) from rdb$relations; + select list(trim(rdb$relation_name), ?) from rdb$relations rows 0; """ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ INPUT message field count: 1 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 4 charset: 4 UTF8 - : name: alias: - : table: owner: - + : name: alias: + : table: owner: PLAN (RDB$RELATIONS NATURAL) - OUTPUT message field count: 1 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8 - : name: LIST alias: LIST - : table: owner: + : name: LIST alias: LIST + : table: owner: """ -# version: 3.0 +expected_stdout_6x = """ + INPUT message field count: 1 + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 4 charset: 4 SYSTEM.UTF8 + : name: alias: + : table: schema: owner: + PLAN ("SYSTEM"."RDB$RELATIONS" NATURAL) + OUTPUT message field count: 1 + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 SYSTEM.UTF8 + : name: LIST alias: LIST + : table: schema: owner: +""" -@pytest.mark.version('>=3.0.1,<4.0') +@pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute(charset='utf8') + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - -# version: 4.0 - -@pytest.mark.version('>=4.0') -def test_2(act: Action): - act.expected_stdout = expected_stdout - act.execute() - assert act.clean_stdout == act.clean_expected_stdout - From e453a272b4f733a968fd4dfb3619d3d08789c526 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 20:47:45 +0300 Subject: [PATCH 0923/1064] Added/Updated tests\bugs\core_5325_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5325_test.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_5325_test.py b/tests/bugs/core_5325_test.py index a63e4878..e536bd03 100644 --- a/tests/bugs/core_5325_test.py +++ b/tests/bugs/core_5325_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5325 FBTEST: bugs.core_5325 + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -22,32 +27,34 @@ act = python_act('db', substitutions=substitutions) test_script = """ - create exception error_test 'йцукенг'; + create exception exc_qwerty 'йцукенг'; commit; set term ^; execute block as begin - exception error_test 'йцу' || _win1251 x'0d0a' || 'кенг'; + exception exc_qwerty 'йцу' || _win1251 x'0d0a' || 'кенг'; end^ set term ;^ """ script_file = temp_file('test-script.sql') -expected_stderr_1 = """ - Statement failed, SQLSTATE = HY000 - exception 1 - -ERROR_TEST - -йцу - - кенг -""" - @pytest.mark.version('>=3.0') def test_1(act: Action, script_file: Path): script_file.write_text(test_script, encoding='cp1251') - act.expected_stderr = expected_stderr_1 - act.isql(switches=['-q'], input_file=script_file, charset='WIN1251') - assert act.clean_stderr == act.clean_expected_stderr + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + EXCEPTION_NAME = ('exc_qwerty' if act.is_version('<6') else '"exc_qwerty"').upper() + expected_out = f""" + Statement failed, SQLSTATE = HY000 + exception 1 + -{SQL_SCHEMA_PREFIX}{EXCEPTION_NAME} + -йцу + + кенг + """ + act.expected_stdout = expected_out + act.isql(switches=['-q'], input_file=script_file, charset='WIN1251', combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 6144063d9980f0f7fa440a7e5c69acd727a88aaa Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 20:56:51 +0300 Subject: [PATCH 0924/1064] Added/Updated tests\bugs\core_5367_test.py: Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5367_test.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/tests/bugs/core_5367_test.py b/tests/bugs/core_5367_test.py index d8f7808f..970e676a 100644 --- a/tests/bugs/core_5367_test.py +++ b/tests/bugs/core_5367_test.py @@ -7,46 +7,38 @@ DESCRIPTION: JIRA: CORE-5367 FBTEST: bugs.core_5367 +NOTES: + [01.07.2025] pzotov + Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. + Added appropriate substitutions. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -init_script = """ - recreate table test(id int,boo boolean); -""" - -db = db_factory(init=init_script) +db = db_factory() test_script = """ + recreate table test(id int, boo boolean); set sqlda_display on; set planonly; select * from test where ?; - set planonly; """ -act = isql_act('db', test_script) + +substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - INPUT message field count: 1 01: sqltype: 32764 BOOLEAN scale: 0 subtype: 0 len: 1 - : name: alias: - : table: owner: - - PLAN (TEST NATURAL) - - OUTPUT message field count: 2 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: ID alias: ID - : table: TEST owner: SYSDBA 02: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - : name: BOO alias: BOO - : table: TEST owner: SYSDBA """ @pytest.mark.version('>=3.0.2') def test_1(act: Action): + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 3f1ec3b1a9271f3f5baf429d4f1005955006084d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:06:25 +0300 Subject: [PATCH 0925/1064] Added/Updated tests\bugs\core_5313_test.py: Added forgotten branch for 3.x. Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5313_test.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_5313_test.py b/tests/bugs/core_5313_test.py index ca8f4cb4..54dd7acb 100644 --- a/tests/bugs/core_5313_test.py +++ b/tests/bugs/core_5313_test.py @@ -9,6 +9,8 @@ FBTEST: bugs.core_5313 NOTES: [01.07.2025] pzotov + Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. + Added appropriate substitutions. Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. @@ -26,34 +28,28 @@ select list(trim(rdb$relation_name), ?) from rdb$relations rows 0; """ -act = isql_act('db', test_script) +substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) + +expected_stdout_3x = """ + 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 3 charset: 3 UNICODE_FSS + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 3 UNICODE_FSS +""" expected_stdout_5x = """ - INPUT message field count: 1 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 4 charset: 4 UTF8 - : name: alias: - : table: owner: - PLAN (RDB$RELATIONS NATURAL) - OUTPUT message field count: 1 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8 - : name: LIST alias: LIST - : table: owner: """ expected_stdout_6x = """ - INPUT message field count: 1 01: sqltype: 452 TEXT scale: 0 subtype: 0 len: 4 charset: 4 SYSTEM.UTF8 - : name: alias: - : table: schema: owner: - PLAN ("SYSTEM"."RDB$RELATIONS" NATURAL) - OUTPUT message field count: 1 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 SYSTEM.UTF8 - : name: LIST alias: LIST - : table: schema: owner: """ + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 16accbe4909801d464adcc049af035c227013a3c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:15:48 +0300 Subject: [PATCH 0926/1064] Added/Updated tests\bugs\core_5380_test.py: Refactored. It is enough for this test to check only presense of 'SQLSTATE = 54001' and 'Too many concurrent executions' in STDERR. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5380_test.py | 38 +++++++++++------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/tests/bugs/core_5380_test.py b/tests/bugs/core_5380_test.py index c0b9f7dc..58960c53 100644 --- a/tests/bugs/core_5380_test.py +++ b/tests/bugs/core_5380_test.py @@ -8,6 +8,12 @@ We check not only ability of recursive calls but also max depth of them. It should be equal to 1000. JIRA: CORE-5380 FBTEST: bugs.core_5380 + [30.06.2025] pzotov + Part of call stack ('At sub function line X col Y') must be supressed because its length is limited to 1024 characters + and number of lines (together with interrupting marker '...') depends on length of function name that is called recursively. + It is enough for this test to check only presense of 'SQLSTATE = 54001' and 'Too many concurrent executions' in STDERR. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -41,40 +47,18 @@ -- (a1 + an) * n / 2 """ -act = isql_act('db', test_script, substitutions=[('line:\\s[0-9]+,', 'line: x'), - ('col:\\s[0-9]+', 'col: y')]) +substitutions = [ ('^((?!(SQLSTATE|Too many concurrent executions|ARITHMETIC_PROGRESSION_TOTAL)).)*$', ''), ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - ARITHMETIC_PROGRESSION_TOTAL 501501 -""" - -expected_stderr = """ + ARITHMETIC_PROGRESSION_TOTAL 501501 Statement failed, SQLSTATE = 54001 Too many concurrent executions of the same request - -At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY' line: 7, col: 13 - At sub function 'GET_SUB_TOTAL_RECURSIVELY'... """ @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d1e6da7f10bf543b8e837c84856288214ee63b8a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:20:07 +0300 Subject: [PATCH 0927/1064] Added/Updated tests\bugs\core_5383_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5383_test.py | 75 +++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_5383_test.py b/tests/bugs/core_5383_test.py index 6b757777..3b5429e9 100644 --- a/tests/bugs/core_5383_test.py +++ b/tests/bugs/core_5383_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5383 FBTEST: bugs.core_5383 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -117,45 +122,63 @@ execute procedure pg_03.p03(1); """ -act = isql_act('db', test_script) +substitutions = [] # [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - - RDB$DEPENDENT_NAME PG_03 - RDB$DEPENDED_ON_NAME TEST01 - - RDB$DEPENDENT_NAME PG_03 - RDB$DEPENDED_ON_NAME TEST02 - - RDB$DEPENDENT_NAME PG_03 - RDB$DEPENDED_ON_NAME TEST03 - - Records affected: 3 - - O_Y 111 - O_Y 222 - O_Y 333 +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST01.ID1 + -there are 1 dependencies + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST02.ID2 + -there are 1 dependencies + + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST01 + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST02 + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST03 + Records affected: 3 + + O_Y 111 + O_Y 222 + O_Y 333 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -COLUMN TEST01.ID1 + -COLUMN "PUBLIC"."TEST01"."ID1" -there are 1 dependencies Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -COLUMN TEST02.ID2 + -COLUMN "PUBLIC"."TEST02"."ID2" -there are 1 dependencies + + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST01 + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST02 + RDB$DEPENDENT_NAME PG_03 + RDB$DEPENDED_ON_NAME TEST03 + Records affected: 3 + + O_Y 111 + O_Y 222 + O_Y 333 """ @pytest.mark.version('>=3.0.2') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 28519854283c196ee77a783302bf7ce97e03e498 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:46:14 +0300 Subject: [PATCH 0928/1064] Added/Updated tests\bugs\core_5404_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5404_test.py | 37 ++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_5404_test.py b/tests/bugs/core_5404_test.py index 6d483722..d9edfc7c 100644 --- a/tests/bugs/core_5404_test.py +++ b/tests/bugs/core_5404_test.py @@ -5,11 +5,16 @@ ISSUE: 5677 TITLE: Inconsistent column/line references when PSQL definitions return errors DESCRIPTION: - ### WARNING ### - Following code is intentionaly aborted in the middle point because some cases are not - covered by fix of this ticket (see also issue in the ticket, 22/Nov/16 06:10 PM). + ### WARNING ### + Following code is intentionaly aborted in the middle point because some cases are not + covered by fix of this ticket (see also issue in the ticket, 22/Nov/16 06:10 PM). JIRA: CORE-5404 FBTEST: bugs.core_5404 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -93,7 +98,7 @@ substitutions=[('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', '-At line: column:')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Dynamic SQL Error -SQL error code = -104 @@ -110,9 +115,25 @@ -At line 4, column 10 """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -Zero length identifiers are not allowed + -At line: column: + + Statement failed, SQLSTATE = 42S22 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."DSQL_FIELD_ERR2" failed + -Dynamic SQL Error + -SQL error code = -206 + -Column unknown + -"FOO" + -At line: column: +""" + @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 561919ffa8d9da5cb3719c7fa4308eb7cc7ed7c7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:50:19 +0300 Subject: [PATCH 0929/1064] Added/Updated tests\bugs\core_5410_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5410_test.py | 47 +++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_5410_test.py b/tests/bugs/core_5410_test.py index 8a2422c4..587afdb2 100644 --- a/tests/bugs/core_5410_test.py +++ b/tests/bugs/core_5410_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5410 FBTEST: bugs.core_5410 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -109,36 +114,50 @@ select pg_test.fn_outer_packaged() as min_f02 from rdb$database; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - MAX_F01 100 - MIN_F01 1 +expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST_1.F01 + -there are 2 dependencies - MAX_F02 200 - MIN_F02 2 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TEST_2.F02 + -there are 1 dependencies + MAX_F01 100 + MIN_F01 1 + MAX_F02 200 + MIN_F02 2 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -COLUMN TEST_1.F01 + -COLUMN "PUBLIC"."TEST_1"."F01" -there are 2 dependencies Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete - -COLUMN TEST_2.F02 + -COLUMN "PUBLIC"."TEST_2"."F02" -there are 1 dependencies + + MAX_F01 100 + MIN_F01 1 + MAX_F02 200 + MIN_F02 2 """ @pytest.mark.version('>=3.0.2') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 63b2ba0b450327549fd6f510a5e83bb2b9b68036 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:52:34 +0300 Subject: [PATCH 0930/1064] Added/Updated tests\bugs\core_5421_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5421_test.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_5421_test.py b/tests/bugs/core_5421_test.py index ef5c233a..52f867c5 100644 --- a/tests/bugs/core_5421_test.py +++ b/tests/bugs/core_5421_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5421 FBTEST: bugs.core_5421 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -62,17 +67,23 @@ """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN SORT (JOIN (C INDEX (C5421_TMAIN_EKEY), D INDEX (C5421_TDETL_DOC_ID))) - DOC_ID 0 + DOC_ID 0 + Records affected: 1 +""" + +expected_stdout_6x = """ + PLAN SORT (JOIN ("C" INDEX ("PUBLIC"."C5421_TMAIN_EKEY"), "D" INDEX ("PUBLIC"."C5421_TDETL_DOC_ID"))) + DOC_ID 0 Records affected: 1 """ @pytest.mark.version('>=3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 3466c013cf7c70e96a6e3611dcbf8ecc3d5c1a58 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 21:58:10 +0300 Subject: [PATCH 0931/1064] Added/Updated tests\bugs\core_5423_test.py: Refactored: suppress output of column name that is unknown - it has no matter for this test. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5423_test.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_5423_test.py b/tests/bugs/core_5423_test.py index 3680951c..b3960eed 100644 --- a/tests/bugs/core_5423_test.py +++ b/tests/bugs/core_5423_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-5423 FBTEST: bugs.core_5423 +NOTES: + [01.07.2025] pzotov + Refactored: suppress output of column name ('foo') that is unknown - it has no matter for this test. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -21,30 +25,21 @@ select 2 k from rdb$database where 1 between 0 and 2 and foo is not null; """ -act = isql_act('db', test_script, - substitutions=[('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', - '-At line: column:')]) +substitutions = [ ('[ \t]+', ' '), ('(-)?(")?FOO(")?', ''), (r'(-)?At line(:)?\s+\d+.*', '') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - K 1 - + K 1 Records affected: 1 -""" - -expected_stderr = """ Statement failed, SQLSTATE = 42S22 Dynamic SQL Error -SQL error code = -206 -Column unknown - -FOO - -At line: column: """ @pytest.mark.version('>=3.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 398e84782f3065b296f8507c707bce21d94a5069 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:02:47 +0300 Subject: [PATCH 0932/1064] Added/Updated tests\bugs\core_5431_test.py: Refactored: suppress output of column name (TEST1.ID) related to validation error - it has no matter for this test. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5431_test.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_5431_test.py b/tests/bugs/core_5431_test.py index d8cd8935..3d293f45 100644 --- a/tests/bugs/core_5431_test.py +++ b/tests/bugs/core_5431_test.py @@ -12,6 +12,10 @@ Adjusted expected_stderr according to notes in #7229. Removed unneeded substitutions and old comments. Confirmed problem on 5.0.0.573 Checked on 5.0.0.958, 4.0.3.2903 - all OK. + + [01.07.2025] pzotov + Refactored: suppress output of column name (TEST1.ID) related to validation error - it has no matter for this test. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -49,23 +53,21 @@ insert into test1 default values returning id as test1_id; """ -act = isql_act('db', test_script) +substitutions = [ ('[ \t]+', ' '), ('validation error for column .*', 'validation error for column') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - IDENTITY_SEQUENCES_COUNT_1 1 - TEST1_ID 32767 - IDENTITY_SEQUENCES_COUNT_2 0 -""" -expected_stderr = """ + IDENTITY_SEQUENCES_COUNT_1 1 + TEST1_ID 32767 + IDENTITY_SEQUENCES_COUNT_2 0 + Statement failed, SQLSTATE = 23000 - validation error for column "TEST1"."ID", value "*** null ***" + validation error for column """ @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0e5b172a717d7e2ca47a10463d465fed8bcdb236 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:11:55 +0300 Subject: [PATCH 0933/1064] Added/Updated tests\bugs\core_5435_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5435_test.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_5435_test.py b/tests/bugs/core_5435_test.py index e449df69..0ffe3bd0 100644 --- a/tests/bugs/core_5435_test.py +++ b/tests/bugs/core_5435_test.py @@ -25,10 +25,10 @@ JIRA: CORE-5435 FBTEST: bugs.core_5435 NOTES: - [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow to specify THE SAME terminator twice, - i.e. - set term @; select 1 from rdb$database @ set term @; - will not compile ("Unexpected end of command" raises). + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -40,10 +40,6 @@ FETCHES_THRESHOLD = 80 -expected_stdout = """ - PLAN (TEST ORDER TEST_F01_ID) -""" - async_init_script = """ recreate table test ( @@ -115,6 +111,11 @@ def test_1(act: Action): if words[k].startswith('fetch'): num_of_fetches = int(words[k - 1]) break - # Check - assert run_with_plan == 'PLAN (TEST ORDER TEST_F01_ID)' + + if act.is_version('<6'): + expected_plan = 'PLAN (TEST ORDER TEST_F01_ID)' + else: + expected_plan = 'PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_F01_ID")' + + assert run_with_plan == expected_plan assert num_of_fetches < FETCHES_THRESHOLD From 6f81f21b21641d6e5753768d86312484fd7fddc2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:15:52 +0300 Subject: [PATCH 0934/1064] Added/Updated tests\bugs\core_5463_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5463_test.py | 51 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_5463_test.py b/tests/bugs/core_5463_test.py index 2a75f86d..4a650963 100644 --- a/tests/bugs/core_5463_test.py +++ b/tests/bugs/core_5463_test.py @@ -17,6 +17,11 @@ "OVERRIDING SYSTEM VALUE should be used to override the value of an identity column defined as 'GENERATED ALWAYS' in table/view ..." New text (after #7638 was fixed): "OVERRIDING clause should be used when an identity column defined as 'GENERATED ALWAYS' is present in the INSERT's field list for table table/view ..." + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -93,33 +98,41 @@ insert into test_default(id_default) overriding user value values(-7654322) returning id_default; -- expected: -121 """ -act = isql_act('db', test_script) - -expected_stdout = """ - ID_DEFAULT -11 - ID_ALWAYS 11 - ID_DEFAULT -7654321 - ID_ALWAYS 7654321 - ID_DEFAULT -33 - ID_DEFAULT -55 -""" +substitutions = [ ('[ \t]+', ' ') ] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ + ID_DEFAULT -11 + ID_ALWAYS 11 Statement failed, SQLSTATE = 42000 OVERRIDING clause should be used when an identity column defined as 'GENERATED ALWAYS' is present in the INSERT's field list for table table/view TEST_ALWAYS - Statement failed, SQLSTATE = 23000 validation error for column "TEST_DEFAULT"."ID_DEFAULT", value "*** null ***" - + ID_DEFAULT -7654321 Statement failed, SQLSTATE = 23000 validation error for column "TEST_ALWAYS"."ID_ALWAYS", value "*** null ***" + ID_ALWAYS 7654321 + ID_DEFAULT -33 + ID_DEFAULT -55 +""" + +expected_stdout_6x = """ + ID_DEFAULT -11 + ID_ALWAYS 11 + Statement failed, SQLSTATE = 42000 + OVERRIDING clause should be used when an identity column defined as 'GENERATED ALWAYS' is present in the INSERT's field list for table table/view "PUBLIC"."TEST_ALWAYS" + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST_DEFAULT"."ID_DEFAULT", value "*** null ***" + ID_DEFAULT -7654321 + Statement failed, SQLSTATE = 23000 + validation error for column "PUBLIC"."TEST_ALWAYS"."ID_ALWAYS", value "*** null ***" + ID_ALWAYS 7654321 + ID_DEFAULT -33 + ID_DEFAULT -55 """ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 42bd354a667ba0cfbf7a410469b0acafa4ee9e0b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:28:14 +0300 Subject: [PATCH 0935/1064] Added/Updated tests\bugs\core_5475_test.py: Adjusted `with pytest.raises(DatabaseError, '...')`: skip check for matching table name (FB 6.x). --- tests/bugs/core_5475_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_5475_test.py b/tests/bugs/core_5475_test.py index f94e0387..669ca2e2 100644 --- a/tests/bugs/core_5475_test.py +++ b/tests/bugs/core_5475_test.py @@ -25,6 +25,9 @@ See letter from Vlad, 31-mar-2020 14:29. JIRA: CORE-5475 FBTEST: bugs.core_5475 +NOTES: + [01.07.2025] pzotov + Adjusted "with pytest.raises(DatabaseError, '...')": skip check for matching table name (FB 6.x). """ import pytest @@ -118,7 +121,7 @@ def test_1(act: Action, capsys): # with act.db.connect(sql_dialect=1) as con: c = con.cursor() - with pytest.raises(DatabaseError, match='.*violation of PRIMARY or UNIQUE KEY constraint "TEST_PK" on table "TEST".*'): + with pytest.raises(DatabaseError, match='.*violation of PRIMARY or UNIQUE KEY constraint.*'): c.execute('insert into test(id,tiny_num) values(?, ?)', [1, 1]) # with act.db.connect(sql_dialect=1) as con: From 37f802eb1501273eb50066946a2cf5a08a72fe6c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:30:41 +0300 Subject: [PATCH 0936/1064] Added/Updated tests\bugs\core_5481_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5481_test.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_5481_test.py b/tests/bugs/core_5481_test.py index 0570115e..d3d006bc 100644 --- a/tests/bugs/core_5481_test.py +++ b/tests/bugs/core_5481_test.py @@ -12,6 +12,12 @@ Execution plan changed in FB 5.x since build 5.0.0.1211 (14-sep-2023). Expected output has been splitted on that remains actual for FB 4.x and one that issued for 5.x+. Confirmed by dimitr, letter 24.09.2023 13:30 + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -74,9 +80,15 @@ PLAN (V_TEST B ORDER BALANCES_BALANCEDATE_DESC INDEX (FK_BALANCES_ORGACCOUNTS)) """ +expected_stdout_6x = """ + PLAN SORT ("PUBLIC"."V_TEST" "B" INDEX ("PUBLIC"."BALANCES_BALANCEDATE_ORGACCOUNT")) + PLAN ("PUBLIC"."V_TEST" "B" ORDER "PUBLIC"."BALANCES_BALANCEDATE_DESC" INDEX ("PUBLIC"."FK_BALANCES_ORGACCOUNTS")) +""" + + @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x - act.execute() + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 9981402392928f9c1d360cc25be6350c14dc3e14 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:34:23 +0300 Subject: [PATCH 0937/1064] Added/Updated tests\bugs\core_5489_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5489_test.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5489_test.py b/tests/bugs/core_5489_test.py index a1c845be..1634dbfd 100644 --- a/tests/bugs/core_5489_test.py +++ b/tests/bugs/core_5489_test.py @@ -27,8 +27,10 @@ JIRA: CORE-5489 FBTEST: bugs.core_5489 NOTES: - [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -115,6 +117,10 @@ def test_1(act: Action): for k in range(len(words)): if words[k].startswith('fetch'): num_of_fetches = int(words[k-1]) - # Check - assert run_with_plan == 'PLAN (TEST ORDER TEST_F01_ID)' + if act.is_version('<6'): + expected_plan = 'PLAN (TEST ORDER TEST_F01_ID)' + else: + expected_plan = 'PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_F01_ID")' + + assert run_with_plan == expected_plan assert num_of_fetches < FETCHES_THRESHOLD From 80ea39905f35aa9f332c0e7427f02076772d607c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:38:44 +0300 Subject: [PATCH 0938/1064] Added/Updated tests\bugs\core_5494_test.py: Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5494_test.py | 41 +++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/bugs/core_5494_test.py b/tests/bugs/core_5494_test.py index 566568ed..cdb5d24c 100644 --- a/tests/bugs/core_5494_test.py +++ b/tests/bugs/core_5494_test.py @@ -7,6 +7,14 @@ DESCRIPTION: JIRA: CORE-5494 FBTEST: bugs.core_5494 +NOTES: + [01.07.2025] pzotov + Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. + Added appropriate substitutions. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -17,9 +25,9 @@ test_script = """ set bail on; recreate table test ( - c1 binary(8), - v1 varbinary(8), - b1 blob sub_type binary + c1 binary(8), + v1 varbinary(8), + b1 blob sub_type binary ); insert into test(c1, b1) values('', ''); @@ -30,28 +38,23 @@ select * from test; """ -act = isql_act('db', test_script) +substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - INPUT message field count: 0 - - PLAN (TEST NATURAL) - - OUTPUT message field count: 3 +expected_stdout_5x = """ 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: C1 alias: C1 - : table: TEST owner: SYSDBA 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 OCTETS - : name: V1 alias: V1 - : table: TEST owner: SYSDBA 03: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 - : name: B1 alias: B1 - : table: TEST owner: SYSDBA +""" + +expected_stdout_6x = """ + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 8 charset: 1 SYSTEM.OCTETS + 03: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 """ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From 1a3af793122cd9d9e2293004f04d3c3b47542bb2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:46:49 +0300 Subject: [PATCH 0939/1064] Added/Updated tests\bugs\core_5536_test.py: Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5536_test.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_5536_test.py b/tests/bugs/core_5536_test.py index 19ba1676..07a5287d 100644 --- a/tests/bugs/core_5536_test.py +++ b/tests/bugs/core_5536_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5536 FBTEST: bugs.core_5536 +NOTES: + [01.07.2025] pzotov + Refactored: we have to check only rows which contain either 'sqltype' or 'SQLSTATE'. + Added appropriate substitutions. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -15,36 +20,24 @@ db = db_factory() test_script = """ - set planonly; set sqlda_display on; select mon$wire_compressed, mon$wire_encrypted from mon$attachments where mon$attachment_id = current_connection ; - -- Fields that were used before: - -- MON$CONNECTION_COMPRESSED in (false, true) - -- and MON$CONNECTION_ENCRYPTED in (false, true) """ -act = isql_act('db', test_script) +substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - INPUT message field count: 0 - - PLAN (MON$ATTACHMENTS NATURAL) - - OUTPUT message field count: 2 01: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - : name: MON$WIRE_COMPRESSED alias: MON$WIRE_COMPRESSED - : table: MON$ATTACHMENTS owner: SYSDBA 02: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - : name: MON$WIRE_ENCRYPTED alias: MON$WIRE_ENCRYPTED - : table: MON$ATTACHMENTS owner: SYSDBA """ @pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 39de8eb966c13dc1018cc3d16f78b88fc4b140b7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:52:24 +0300 Subject: [PATCH 0940/1064] Added/Updated tests\bugs\core_5567_test.py: Refactored: suppressed name of system table as it has no matter for this test. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5567_test.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_5567_test.py b/tests/bugs/core_5567_test.py index 9a09ca43..2869232b 100644 --- a/tests/bugs/core_5567_test.py +++ b/tests/bugs/core_5567_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5567 FBTEST: bugs.core_5567 +NOTES: + [01.07.2025] pzotov + Refactored: suppressed name of system table as it has no matter for this test. + Added appropriate substitutions. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -49,23 +54,18 @@ """ -act = isql_act('db', test_script, substitutions=[('line: [\\d]+, col: [\\d]+', ''), ('.*At block.*', '')]) +substitutions = [('[ \t]+', ' '), (r'line(:)?\s+\d+', ''), ('.*At block.*', ''), ('(-)?At sub procedure.*', ''), ('for system table .*', 'for system table')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - DOMAIN_PRECISION -2 -""" - -expected_stderr = """ Statement failed, SQLSTATE = 42000 - UPDATE operation is not allowed for system table RDB$FIELDS - -At sub procedure 'HACK' + UPDATE operation is not allowed for system table + DOMAIN_PRECISION -2 """ @pytest.mark.version('>=3.0.3') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From c1f2b711a1c281327cc54b78c0e95260c8ef50d3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:55:31 +0300 Subject: [PATCH 0941/1064] Added/Updated tests\bugs\core_5576_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5576_test.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_5576_test.py b/tests/bugs/core_5576_test.py index 73baa6fe..54e1edf0 100644 --- a/tests/bugs/core_5576_test.py +++ b/tests/bugs/core_5576_test.py @@ -12,6 +12,12 @@ Neither test query nor validation should raise any output in the STDERR. JIRA: CORE-5576 FBTEST: bugs.core_5576 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -37,7 +43,7 @@ X1 1 """ -expected_stdout_b = """ +expected_stdout_b_5x = """ Validation started Relation 128 (TEST) process pointer page 0 of 1 @@ -46,6 +52,15 @@ Validation finished """ +expected_stdout_b_6x = """ + Validation started + Relation ("PUBLIC"."TEST") + process pointer page 0 of 1 + Index 1 ("PUBLIC"."RDB$PRIMARY1") + Relation ("PUBLIC"."TEST") is ok + Validation finished +""" + fbk_file = temp_file('core_5576.fbk') fdb_file = temp_file('core_5576.fdb') @@ -63,7 +78,9 @@ def test_1(act: Action, fbk_file: Path, fdb_file: Path): assert act.clean_stdout == act.clean_expected_stdout # Validate the database act.reset() - act.expected_stdout = expected_stdout_b + + act.expected_stdout = expected_stdout_b_5x if act.is_version('<6') else expected_stdout_b_6x + with act.connect_server() as srv: srv.database.validate(database=fdb_file) act.stdout = ''.join(srv.readlines()) From d204d83103a5b6a2deea910a291cc8e909226132 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 22:57:41 +0300 Subject: [PATCH 0942/1064] Added/Updated tests\bugs\core_5580_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5580_test.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5580_test.py b/tests/bugs/core_5580_test.py index 2ec41bfc..0b39f795 100644 --- a/tests/bugs/core_5580_test.py +++ b/tests/bugs/core_5580_test.py @@ -7,6 +7,12 @@ DESCRIPTION: JIRA: CORE-5580 FBTEST: bugs.core_5580 +NOTES: + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -47,19 +53,34 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -RECREATE PACKAGE BODY PK1 failed -Function F1 has a signature mismatch on package body PK1 + Statement failed, SQLSTATE = 2F000 Cannot execute function F1 of the unimplemented package PK1 + Statement failed, SQLSTATE = 2F000 Cannot execute function F2 of the unimplemented package PK1 """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE PACKAGE BODY "PUBLIC"."PK1" failed + -Function F1 has a signature mismatch on package body "PUBLIC"."PK1" + + Statement failed, SQLSTATE = 2F000 + Cannot execute function "F1" of the unimplemented package "PUBLIC"."PK1" + + Statement failed, SQLSTATE = 2F000 + Cannot execute function "F2" of the unimplemented package "PUBLIC"."PK1" +""" + @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 4f869585db926a4a416aecb4864faadbbe56b5bb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Tue, 1 Jul 2025 23:01:14 +0300 Subject: [PATCH 0943/1064] Added/Updated tests\bugs\core_5598_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5598_test.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5598_test.py b/tests/bugs/core_5598_test.py index bb5e5bf1..db88d82c 100644 --- a/tests/bugs/core_5598_test.py +++ b/tests/bugs/core_5598_test.py @@ -3,8 +3,7 @@ """ ID: issue-5864 ISSUE: 5864 -TITLE: Error "block size exceeds implementation restriction" while inner joining large - datasets with a long key using the HASH JOIN plan +TITLE: Error "block size exceeds implementation restriction" while inner joining large datasets with a long key using the HASH JOIN plan DESCRIPTION: Hash join have to operate with keys of total length >= 1 Gb if we want to reproduce runtime error "Statement failed, SQLSTATE = HY001 / unable to allocate memory from operating system" @@ -30,7 +29,7 @@ ======== (Captured ISQL stderr call): Statement failed, SQLSTATE = 08001 - I/O error during "CreateFile (create)" operation for file "R:\RAMDISK\fb_recbuf_py6oyh" + I/O error during "CreateFile (create)" operation for file "\fb_recbuf_py6oyh" -Error while trying to create file -[ The system cannot find the path specified ] -- CAN BE LOCALIZED. ======== @@ -39,6 +38,12 @@ act.isql(switches = ..., input = ..., charset = ..., io_enc=locale.getpreferredencoding()) NOTE: specifying 'encoding_errors = ignore' in the DEFAULT section of firebird-driver.conf does not prevent from UnicodeDecode error in this case. + + [01.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -60,6 +65,10 @@ PLAN HASH (A NATURAL, B NATURAL) """ +fb6x_checked_stdout = """ + PLAN HASH ("A" NATURAL, "B" NATURAL) +""" + MIN_RECS_TO_ADD = 17000 test_script = """ @@ -79,7 +88,7 @@ def test_1(act: Action): c.execute(f"insert into test(id, s) select row_number()over(), lpad('', 8191, 'Алексей, Łukasz, Máté, François, Jørgen, Νικόλαος') from rdb$types,rdb$types rows {MIN_RECS_TO_ADD}") con.commit() - act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout + act.expected_stdout = fb3x_checked_stdout if act.is_version('<5') else fb5x_checked_stdout if act.is_version('<6') else fb6x_checked_stdout # NB: FIREBIRD_TMP must point do accessible directory here! act.isql(switches=['-q'], input=test_script, charset='UTF8', io_enc=locale.getpreferredencoding()) From ab3a24cf4bf73bcb317668372aa24fcdafd247d7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 11:39:25 +0300 Subject: [PATCH 0944/1064] Added/Updated tests\bugs\core_5673_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5673_test.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_5673_test.py b/tests/bugs/core_5673_test.py index 0416abc7..b7566600 100644 --- a/tests/bugs/core_5673_test.py +++ b/tests/bugs/core_5673_test.py @@ -5,7 +5,6 @@ ISSUE: 5939 TITLE: Unique constraint not working in encrypted database on first command DESCRIPTION: - Test uses Firebird built-in encryption plugin wich actually does encryption using trivial algorithm. Before running this test following prerequisites must be met: 1. Files fbSampleDbCrypt.conf and libfbSampleDbCrypt.so/fbSampleDbCrypt.dll must present in the $FB_HOME/plugins folder; @@ -26,13 +25,19 @@ that encryption/decryption thread completed. Otherwise we loop until such conditions will raise or timeout expired. After this we make TWO attempts to insert duplicates and catch exceptions for each of them and print exception details. - Expected result: two exception must occur here -- see 'expected_stdout_uniq_violation' variable. + Expected result: two exception must occur here. JIRA: CORE-5673 FBTEST: bugs.core_5673 NOTES: [06.06.2022] pzotov Checked on 4.0.1.2692, 3.0.8.33535 - both on Linux and Windows. + + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import os import time @@ -134,13 +139,6 @@ def test_1(act: Action, capsys): #------------------------------------------------------------------------------------------------------ - expected_stdout_uniq_violation = f""" - violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" - -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) - violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" - -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) - """ - tx2 = con.transaction_manager(default_tpb=custom_tpb.get_buffer()) tx2.begin() cur2 = tx2.cursor() @@ -156,7 +154,21 @@ def test_1(act: Action, capsys): print( e.__str__() ) - act.expected_stdout = expected_stdout_uniq_violation + expected_stdout_5x = f""" + violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) + violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "TEST" + -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) + """ + + expected_stdout_6x = f""" + violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "PUBLIC"."TEST" + -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) + violation of PRIMARY or UNIQUE KEY constraint "TEST_UNQ" on table "PUBLIC"."TEST" + -Problematic key value is ("DB_STATE" = '{m}', "X" = 1) + """ + + 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 act.reset() From 02438a99e229febf065496e66d0d17f8fc88cb91 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 11:48:34 +0300 Subject: [PATCH 0945/1064] Added/Updated tests\bugs\core_5674_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5674_test.py | 53 ++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_5674_test.py b/tests/bugs/core_5674_test.py index 0959f098..7eb58cac 100644 --- a/tests/bugs/core_5674_test.py +++ b/tests/bugs/core_5674_test.py @@ -9,12 +9,15 @@ FBTEST: bugs.core_5674 NOTES: [19.07.2023] pzotov - Adjusted expected error text for FB 4.x and 5.x: it now contains not only errors but also warnings about non-used CTEs. + Adjusted expected error text for FB 4.x and 5.x: it now contains not only errors but also warnings about non-used CTEs. [12.08.2023] pzotov - Adjusted expected error text for FB 3.0.12: now it is the same as for FB 4.x+ - - Change caused by commit "Print warnings occurred during commit", date: 07-jul-2023, started on builds 4.0.3.2958 and 5.0.0.1101. - Discussed with Vlad, 10-jul-2023. + Adjusted expected error text for FB 3.0.12: now it is the same as for FB 4.x+ + Change caused by commit "Print warnings occurred during commit", date: 07-jul-2023, started on builds 4.0.3.2958 and 5.0.0.1101. + Discussed with Vlad, 10-jul-2023. + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -109,15 +112,14 @@ """ -act = isql_act('db', test_script, - substitutions=[('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', - '-At line: column:')]) +substitutions = [ ('[ \t]+', ' '), ('(-)?At line \\d+.*', '') ] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - Y 2 - X 4 + Y 2 + X 4 - X 0 + X 0 """ @pytest.mark.version('>=3.0.3') @@ -146,7 +148,7 @@ def test_1(act: Action): -SQL error code = -104 -CTE 'C' has cyclic dependencies """ - else: + elif act.is_version('<6'): act.expected_stderr = """ SQL warning code = -104 -CTE "X" is not used in query @@ -175,6 +177,33 @@ def test_1(act: Action): -CTE "B" is not used in query -CTE "C" is not used in query """ + else: + act.expected_stderr = """ + SQL warning code = -104 + -CTE "X" is not used in query + -CTE "Y" is not used in query + SQL warning code = -104 + -CTE "B" is not used in query + -CTE "C" is not used in query + -CTE "D" is not used in query + + Statement failed, SQLSTATE = 42S02 + Dynamic SQL Error + -SQL error code = -204 + -Table unknown + -"FOO" + SQL warning code = -104 + -CTE "B" is not used in query + -CTE "C" is not used in query + + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -CTE '"C"' has cyclic dependencies + SQL warning code = -104 + -CTE "B" is not used in query + -CTE "C" is not used in query + """ act.execute() assert (act.clean_stderr == act.clean_expected_stderr and From 37fe89eb42efcf78f3af14689c89afae6f2e3d59 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 11:51:24 +0300 Subject: [PATCH 0946/1064] Added/Updated tests\bugs\core_5676_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5676_test.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_5676_test.py b/tests/bugs/core_5676_test.py index 50263d01..6b347185 100644 --- a/tests/bugs/core_5676_test.py +++ b/tests/bugs/core_5676_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5676 FBTEST: bugs.core_5676 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -51,16 +56,24 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) - PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) - PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) - PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) -""" - @pytest.mark.version('>=3.0.3') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + + expected_stdout_5x = """ + PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + PLAN JOIN (DOC_IP_DOC ORDER PK_DOC_IP_DOC, DOCUMENT INDEX (PK_DOCUMENT)) + """ + + expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."DOC_IP_DOC" ORDER "PUBLIC"."PK_DOC_IP_DOC", "PUBLIC"."DOCUMENT" INDEX ("PUBLIC"."PK_DOCUMENT")) + PLAN JOIN ("PUBLIC"."DOC_IP_DOC" ORDER "PUBLIC"."PK_DOC_IP_DOC", "PUBLIC"."DOCUMENT" INDEX ("PUBLIC"."PK_DOCUMENT")) + PLAN JOIN ("PUBLIC"."DOC_IP_DOC" ORDER "PUBLIC"."PK_DOC_IP_DOC", "PUBLIC"."DOCUMENT" INDEX ("PUBLIC"."PK_DOCUMENT")) + PLAN JOIN ("PUBLIC"."DOC_IP_DOC" ORDER "PUBLIC"."PK_DOC_IP_DOC", "PUBLIC"."DOCUMENT" INDEX ("PUBLIC"."PK_DOCUMENT")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 5c53dbf37844e286118d33ad65201b7e8db6487a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 11:58:46 +0300 Subject: [PATCH 0947/1064] Added/Updated tests\bugs\core_5685_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33794. --- tests/bugs/core_5685_test.py | 58 ++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_5685_test.py b/tests/bugs/core_5685_test.py index 8fa3a885..1f4631f5 100644 --- a/tests/bugs/core_5685_test.py +++ b/tests/bugs/core_5685_test.py @@ -47,6 +47,10 @@ [09.07.2024] pzotov Added item to substitutions related to 'port detached' message that raises in dev build. Fixed wrong logic because of missed indentation, see hang_stderr. + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import platform import pytest @@ -98,32 +102,6 @@ act = python_act('db', substitutions=substitutions) -expected_stdout = """ - HANGED ATTACH, STDOUT: Records affected: 0 - HANGED ATTACH, STDERR: Statement failed, SQLSTATE = 42000 - HANGED ATTACH, STDERR: Execute statement error at isc_dsql_fetch : - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: Statement : select u.unreachable_address from sp_unreachable as u - .*Data source - HANGED ATTACH, STDERR: -At procedure 'SP_GET_DATA' line: 3, col: 9 - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - HANGED ATTACH, STDERR: - KILLER ATTACH, STDOUT: ITERATION_NO 1 - KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION 1 - KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL TCP - KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE 1 - KILLER ATTACH, STDOUT: select * from sp_get_data - KILLER ATTACH, STDOUT: Records affected: 1 - KILLER ATTACH, STDOUT: ITERATION_NO 2 - KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION - KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL - KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE - KILLER ATTACH, STDOUT: Records affected: 0 -""" - - kill_script = """ set list on; set blob all; @@ -213,6 +191,34 @@ def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path, output.append(f"KILLER ATTACH, STDOUT: {' '.join(line.split())}") act.reset() + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + STORED_PROC_NAME = "'SP_GET_DATA'" if act.is_version('<6') else '"SP_GET_DATA"' + expected_stdout = f""" + HANGED ATTACH, STDOUT: Records affected: 0 + HANGED ATTACH, STDERR: Statement failed, SQLSTATE = 42000 + HANGED ATTACH, STDERR: Execute statement error at isc_dsql_fetch : + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: Statement : select u.unreachable_address from sp_unreachable as u + .*Data source + HANGED ATTACH, STDERR: -At procedure {SQL_SCHEMA_PREFIX}{STORED_PROC_NAME} line: 3, col: 9 + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + HANGED ATTACH, STDERR: + KILLER ATTACH, STDOUT: ITERATION_NO 1 + KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION 1 + KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL TCP + KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE 1 + KILLER ATTACH, STDOUT: select * from sp_get_data + KILLER ATTACH, STDOUT: Records affected: 1 + KILLER ATTACH, STDOUT: ITERATION_NO 2 + KILLER ATTACH, STDOUT: HANGING_ATTACH_CONNECTION + KILLER ATTACH, STDOUT: HANGING_ATTACH_PROTOCOL + KILLER ATTACH, STDOUT: HANGING_STATEMENT_STATE + KILLER ATTACH, STDOUT: Records affected: 0 + """ + act.expected_stdout = expected_stdout act.stdout = '\n'.join(output) assert act.clean_stdout == act.clean_expected_stdout From d9cc7a76089427df92d86aa53ef8f87d87fb344c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 12:40:24 +0300 Subject: [PATCH 0948/1064] Added/Updated tests\bugs\core_5737_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5737_test.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_5737_test.py b/tests/bugs/core_5737_test.py index 248cf72d..17495a06 100644 --- a/tests/bugs/core_5737_test.py +++ b/tests/bugs/core_5737_test.py @@ -17,6 +17,11 @@ Confirmed bug on 3.0.3.32837 and 4.0.0.800 (ISQL did hang when issued any of 'SHOW TABLE' / 'SHOW INDEX' copmmand). JIRA: CORE-5737 FBTEST: bugs.core_5737 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -29,11 +34,6 @@ act = python_act('db') -expected_stdout = """ - TEST1 - TEST1_ID_PK_DESC UNIQUE DESCENDING INDEX ON TEST1(ID) -""" - show_script = temp_file('show_script.sql') show_output = temp_file('show_script.out') @@ -56,7 +56,17 @@ def test_1(act: Action, show_script: Path, show_output: Path): time.sleep(4) finally: p_show_sql.terminate() - # - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + TEST1 + TEST1_ID_PK_DESC UNIQUE DESCENDING INDEX ON TEST1(ID) + """ + + expected_stdout_6x = """ + PUBLIC.TEST1 + PUBLIC.TEST1_ID_PK_DESC UNIQUE DESCENDING INDEX ON TEST1(ID) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.stdout = show_output.read_text() assert act.clean_stdout == act.clean_expected_stdout From 2392df93539559a149efb30da5890b5b9cfa53e2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 12:47:26 +0300 Subject: [PATCH 0949/1064] Added/Updated tests\bugs\core_5743_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5743_test.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5743_test.py b/tests/bugs/core_5743_test.py index 89c57f61..4a2232f0 100644 --- a/tests/bugs/core_5743_test.py +++ b/tests/bugs/core_5743_test.py @@ -32,24 +32,31 @@ (periode = ?) group by 1 ; + set planonly; -- sample from CORE-5749: select 'my constant ' as dsc, count( * ) from rdb$relations a - where a.rdb$system_flag = 99 + where a.rdb$system_flag = -2147483648 group by 1 ; """ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN SORT (JOURNAL_CAISSE INDEX (JOURNAL_CAISSE_IDX)) PLAN SORT (A NATURAL) """ +expected_stdout_6x = """ + PLAN SORT ("PUBLIC"."JOURNAL_CAISSE" INDEX ("PUBLIC"."JOURNAL_CAISSE_IDX")) + PLAN SORT ("A" NATURAL) +""" + + @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1c33679a324a575faa1c01a39e6dcc55735ed56b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 14:26:39 +0300 Subject: [PATCH 0950/1064] Added/Updated tests\bugs\core_5747_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5747_test.py | 57 +++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_5747_test.py b/tests/bugs/core_5747_test.py index 1d58be5e..b3fbd589 100644 --- a/tests/bugs/core_5747_test.py +++ b/tests/bugs/core_5747_test.py @@ -8,15 +8,16 @@ beside generator we also have to check the same issue about grant usage on exception. JIRA: CORE-5747 FBTEST: bugs.core_5747 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('no G privilege with grant option on object .*', - 'no USAGE privilege with grant option on object'), - ('GEN_FOR_DBA_ONLY', ''), ('EXC_FOR_DBA_ONLY', '')] - db = db_factory() test_script = """ @@ -56,11 +57,13 @@ """ -act = isql_act('db', test_script, substitutions=substitutions) +substitutions = [('no G privilege with grant option on object .*', + 'no USAGE privilege with grant option on object'), + ('GEN_FOR_DBA_ONLY', ''), ('EXC_FOR_DBA_ONLY', '')] -# version: 3.0 +act = isql_act('db', test_script, substitutions=substitutions) -expected_stderr_1 = """ +expected_stdout_3x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed @@ -75,36 +78,44 @@ no permission for USAGE access to EXCEPTION """ -@pytest.mark.version('>=3.0.4,<4.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr_1 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - -# version: 4.0 - -expected_stderr_2 = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no USAGE privilege with grant option on object - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no USAGE privilege with grant option on object - Statement failed, SQLSTATE = 28000 no permission for USAGE access to GENERATOR -Effective user is TMP$C5747 - Statement failed, SQLSTATE = 28000 no permission for USAGE access to EXCEPTION -Effective user is TMP$C5747 """ -@pytest.mark.version('>=4.0') +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no USAGE privilege with grant option on object "PUBLIC"."" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no USAGE privilege with grant option on object "PUBLIC"."" + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to GENERATOR "PUBLIC"."" + -Effective user is TMP$C5747 + Statement failed, SQLSTATE = 28000 + no permission for USAGE access to EXCEPTION "PUBLIC"."" + -Effective user is TMP$C5747 +""" + + +@pytest.mark.version('>=3.0') def test_2(act: Action): - act.expected_stderr = expected_stderr_2 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 14610d3e34487650d5785c01df5eee1a4f6a784d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 14:32:28 +0300 Subject: [PATCH 0951/1064] Added/Updated tests\bugs\core_5755_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5755_test.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_5755_test.py b/tests/bugs/core_5755_test.py index 0ff6da02..df750a85 100644 --- a/tests/bugs/core_5755_test.py +++ b/tests/bugs/core_5755_test.py @@ -5,10 +5,15 @@ ISSUE: 6018 TITLE: No error if the GRANT target object does not exist DESCRIPTION: - grant execute on proc|func|package and grant usage on sequence|exception -- still does NOT produce error/warning. - These statements temply disabled until some additional comments in tracker. + grant execute on proc|func|package and grant usage on sequence|exception -- still does NOT produce error/warning. + These statements temply disabled until some additional comments in tracker. JIRA: CORE-5755 FBTEST: bugs.core_5755 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -53,11 +58,6 @@ grant select on table_test to function wrong_func; - /************ - - TEMPLY DISABLED, SEE ISSUE IN THE TICKET, 02-JUN-2018 08:20 - =============== - grant execute on procedure sp_test to wrong_func; grant execute on function fn_test to wrong_func; @@ -68,24 +68,36 @@ grant usage on exception x_test to wrong_func; - **************/ """ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -Function WRONG_FUNC does not exist + Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -Function WRONG_FUNC does not exist """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Function "PUBLIC"."WRONG_FUNC" does not exist + + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Function "PUBLIC"."WRONG_FUNC" does not exist +""" + @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 586565703bb47b72c222146df74e660b2b7f14b3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 14:45:58 +0300 Subject: [PATCH 0952/1064] Added/Updated tests\bugs\core_5756_test.py: Confirmed bug (crash) on 3.0.3.32900. Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5756_test.py | 45 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_5756_test.py b/tests/bugs/core_5756_test.py index d5a10c13..f5d71591 100644 --- a/tests/bugs/core_5756_test.py +++ b/tests/bugs/core_5756_test.py @@ -7,6 +7,13 @@ DESCRIPTION: JIRA: CORE-5756 FBTEST: bugs.core_5756 + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Difference between current_connection values must be checked to be sure that there was no crash, see 'ATT_DIFF' + + Confirmed bug (crash) on 3.0.3.32900. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -19,28 +26,42 @@ recreate table test(x int); insert into test values(1); select * from test; + set term ^; + execute block as + begin + rdb$set_context('USER_SESSION', 'INIT_ATT', current_connection); + end ^ + set term ;^ + recreate table test(x int, y int); -- this led to crash - commit; + select * from test; + select current_connection - cast( rdb$get_context('USER_SESSION', 'INIT_ATT') as int) as att_diff from rdb$database; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - X 1 - X 1 +expected_stdout_5x = """ + X 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -object TABLE "TEST" is in use + X 1 + ATT_DIFF 0 """ -expected_stderr = """ +expected_stdout_6x = """ + X 1 Statement failed, SQLSTATE = 42000 unsuccessful metadata update - -object TABLE "TEST" is in use + -object TABLE "PUBLIC"."TEST" is in use + X 1 + ATT_DIFF 0 """ @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d35392884031a8eeecac5a9f134e2cabef249560 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 14:51:47 +0300 Subject: [PATCH 0953/1064] Added/Updated tests\bugs\core_5794_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5794_test.py | 48 ++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/tests/bugs/core_5794_test.py b/tests/bugs/core_5794_test.py index 23b0ff38..7548f375 100644 --- a/tests/bugs/core_5794_test.py +++ b/tests/bugs/core_5794_test.py @@ -13,6 +13,11 @@ "Since Firebird3 <..> cursor doesn't see the changes made by "inner" statements." JIRA: CORE-5794 FBTEST: bugs.core_5794 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -67,30 +72,41 @@ select mon$variable_name as ctx_var, mon$variable_value as ctx_value from mon$context_variables; """ -act = isql_act('db', test_script, substitutions=[('line:\\s[0-9]+,', 'line: x'), - ('col:\\s[0-9]+', 'col: y')]) +substitutions = [ ('[ \t]+', ' '), ( r'line(:)?\s+\d+.*', '' ) ] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - CTX_VAR TRIGGER_OLD_ID - CTX_VALUE 1 +expected_stdout_5x = """ + Statement failed, SQLSTATE = HY000 + exception 1 + -TEST_EXCEPTION + -it is forbidden to delete row with val>0 (id = 1, val=10) + -At trigger 'TEST_TABLE_BD' + At block - CTX_VAR TRIGGER_OLD_VAL - CTX_VALUE 10 + CTX_VAR TRIGGER_OLD_ID + CTX_VALUE 1 + + CTX_VAR TRIGGER_OLD_VAL + CTX_VALUE 10 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = HY000 exception 1 - -TEST_EXCEPTION + -"PUBLIC"."TEST_EXCEPTION" -it is forbidden to delete row with val>0 (id = 1, val=10) - -At trigger 'TEST_TABLE_BD' line: 6, col: 9 - At block line: 16, col: 9 + -At trigger "PUBLIC"."TEST_TABLE_BD" + At block + + CTX_VAR TRIGGER_OLD_ID + CTX_VALUE 1 + + CTX_VAR TRIGGER_OLD_VAL + CTX_VALUE 10 """ @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 77382d99e83dceed93a0c304a50aa87c2eba595b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:23:46 +0300 Subject: [PATCH 0954/1064] Added/Updated tests\bugs\core_5840_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5840_test.py | 76 +++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/tests/bugs/core_5840_test.py b/tests/bugs/core_5840_test.py index 3e9a6959..92f723ff 100644 --- a/tests/bugs/core_5840_test.py +++ b/tests/bugs/core_5840_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5840 FBTEST: bugs.core_5840 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -63,77 +68,84 @@ commit; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - RDB$RELATION_NAME TEST1 - RDB$RELATION_NAME TEST3 -""" - -# version: 3.0.4 - -expected_stderr_1 = """ +expected_stdout_3x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update -CREATE TABLE TEST2 failed -no permission for REFERENCES access to TABLE TEST1 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST3 failed -no permission for ALTER access to TABLE TEST3 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST1 failed -no permission for ALTER access to TABLE TEST1 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST1 failed -no permission for ALTER access to TABLE TEST1 + RDB$RELATION_NAME TEST1 + RDB$RELATION_NAME TEST3 """ -@pytest.mark.version('>=3.0.4,<4.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_1 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) - -# version: 4.0 - -expected_stderr_2 = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update -CREATE TABLE TEST2 failed -no permission for REFERENCES access to TABLE TEST1 -Effective user is TMP$C5840 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST3 failed -no permission for ALTER access to TABLE TEST3 -Effective user is TMP$C5840 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST1 failed -no permission for ALTER access to TABLE TEST1 -Effective user is TMP$C5840 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update -ALTER TABLE TEST1 failed -no permission for ALTER access to TABLE TEST1 -Effective user is TMP$C5840 + RDB$RELATION_NAME TEST1 + RDB$RELATION_NAME TEST3 """ -@pytest.mark.version('>=4.0') +expected_stdout_6x = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE TABLE "PUBLIC"."TEST2" failed + -no permission for REFERENCES access to TABLE "PUBLIC"."TEST1" + -Effective user is TMP$C5840 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST3" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST3" + -Effective user is TMP$C5840 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST1" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST1" + -Effective user is TMP$C5840 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST1" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST1" + -Effective user is TMP$C5840 + RDB$RELATION_NAME TEST1 + RDB$RELATION_NAME TEST3 +""" + + +@pytest.mark.version('>=3.0') def test_2(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr_2 - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0aec7ca797b29780f8eec5a6ded5f1cc38f15326 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:27:27 +0300 Subject: [PATCH 0955/1064] Added/Updated tests\bugs\core_5843_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5843_test.py | 94 +++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/tests/bugs/core_5843_test.py b/tests/bugs/core_5843_test.py index 056f3406..873c237d 100644 --- a/tests/bugs/core_5843_test.py +++ b/tests/bugs/core_5843_test.py @@ -8,18 +8,15 @@ JIRA: CORE-5843 FBTEST: bugs.core_5843 NOTES: - [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc). + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * -substitutions = [('line[:]{0,1}[\\s]+[\\d]+.*', 'line'), - ('transaction[\\s]+[\\d]+[\\s]+aborted', 'transaction aborted'), - ('tx=[\\d]+', 'tx='), ('TX_ID[\\s]+[\\d]+', 'TX_ID'), - ('exception[\\s]+[\\d]+.*', 'exception')] - init_script = """ --set echo on; set bail on; @@ -157,50 +154,79 @@ """ +substitutions = [('[ \t]+', ' '), + ('line[:]{0,1}[\\s]+[\\d]+.*', 'line'), + ('transaction[\\s]+[\\d]+[\\s]+aborted', 'transaction aborted'), + ('tx=[\\d]+', 'tx='), ('TX_ID[\\s]+[\\d]+', 'TX_ID'), + ('exception[\\s]+[\\d]+.*', 'exception')] + act = isql_act('db', test_script, substitutions=substitutions) -expected_stdout = """ +expected_stdout_5x = """ MSG test_1, point-1 - TX_ID 22 + TX_ID 19 TX_STATE 1 - + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_TRA_START + -transaction 20 aborted + -At trigger 'TX_START' line: 10, col: 13 MSG test_1, point-3 - TX_ID 25 + TX_ID 22 TX_STATE 1 Records affected: 1 - MSG test2, point-a - TX_ID 28 + TX_ID 24 TX_STATE 1 + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_TRA_START + -transaction 25 aborted + -At trigger 'TX_START' line: 10, col: 13 + At procedure 'SP_USE_ATX' line: 5, col: 9 RDB$GET_CONTEXT - start: tx=26 - trigger on commit, current tx=26 - trigger on transaction start, current tx=28 - sp_use_atx, point_a, current tx=28 - trigger on transaction start, current tx=29 - exception on tx start, current tx=29 - + start: tx=23 + trigger on commit, current tx=23 + trigger on transaction start, current tx=24 + sp_use_atx, point_a, current tx=24 + trigger on transaction start, current tx=25 + exception on tx start, current tx=25 """ -expected_stderr = """ +expected_stdout_6x = """ + MSG test_1, point-1 + TX_ID 19 + TX_STATE 1 Statement failed, SQLSTATE = HY000 exception 1 - -EX_TRA_START - -transaction 23 aborted - -At trigger 'TX_START' line - + -"PUBLIC"."EX_TRA_START" + -transaction 20 aborted + -At trigger "PUBLIC"."TX_START" line: 10, col: 13 + MSG test_1, point-3 + TX_ID 22 + TX_STATE 1 + Records affected: 1 + MSG test2, point-a + TX_ID 24 + TX_STATE 1 Statement failed, SQLSTATE = HY000 exception 1 - -EX_TRA_START - -transaction 29 aborted - -At trigger 'TX_START' line - At procedure 'SP_USE_ATX' line + -"PUBLIC"."EX_TRA_START" + -transaction 25 aborted + -At trigger "PUBLIC"."TX_START" line: 10, col: 13 + At procedure "PUBLIC"."SP_USE_ATX" line: 5, col: 9 + RDB$GET_CONTEXT + start: tx=23 + trigger on commit, current tx=23 + trigger on transaction start, current tx=24 + sp_use_atx, point_a, current tx=24 + trigger on transaction start, current tx=25 + exception on tx start, current tx=25 """ @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From a23bba9d46b3b20657f5f7e1b5d1ec1e036b50ab Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:30:28 +0300 Subject: [PATCH 0956/1064] Added/Updated tests\bugs\core_5852_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5852_test.py | 38 ++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_5852_test.py b/tests/bugs/core_5852_test.py index 515c78b1..93e223a0 100644 --- a/tests/bugs/core_5852_test.py +++ b/tests/bugs/core_5852_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5852 FBTEST: bugs.core_5852 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -62,31 +67,40 @@ act = isql_act('db', test_script) -expected_stdout = """ - Records affected: 0 -""" - -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -Exception NO_SUCH_EXC does not exist - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -Generator/Sequence NO_SUCH_GEN does not exist - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -Generator/Sequence NO_SUCH_SEQ does not exist + Records affected: 0 +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Exception "PUBLIC"."NO_SUCH_EXC" does not exist + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Generator/Sequence "PUBLIC"."NO_SUCH_GEN" does not exist + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -Generator/Sequence "PUBLIC"."NO_SUCH_SEQ" does not exist + Records affected: 0 """ @pytest.mark.version('>=3.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 998b0e7b7192af71a08a2f6deae8e2da1aa6ad4f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:34:52 +0300 Subject: [PATCH 0957/1064] Added/Updated tests\bugs\core_5861_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5861_test.py | 67 +++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/tests/bugs/core_5861_test.py b/tests/bugs/core_5861_test.py index c983286f..00553ca0 100644 --- a/tests/bugs/core_5861_test.py +++ b/tests/bugs/core_5861_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-5861 FBTEST: bugs.core_5861 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -124,60 +129,88 @@ commit;*/ """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ RDB$ROLE_NAME ROLE1 F GEN_ID 1 -""" - -expected_stderr = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no CREATE privilege with grant option on DDL SQL$TABLES - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no EXECUTE privilege with grant option on object P - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no EXECUTE privilege with grant option on object F - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no USAGE privilege with grant option on object G - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no USAGE privilege with grant option on object E - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no grant option for privilege SELECT on table/view TAB - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no grant option for privilege UPDATE on column ID of table/view TAB - Statement failed, SQLSTATE = 42000 unsuccessful metadata update -GRANT failed -no EXECUTE privilege with grant option on object PAK """ +expected_stdout_6x = """ + RDB$ROLE_NAME ROLE1 + F + GEN_ID 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no CREATE privilege with grant option on DDL "PUBLIC"."SQL$TABLES" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no EXECUTE privilege with grant option on object "PUBLIC"."P" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no EXECUTE privilege with grant option on object "PUBLIC"."F" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no USAGE privilege with grant option on object "PUBLIC"."G" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no USAGE privilege with grant option on object "PUBLIC"."E" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no grant option for privilege SELECT on table/view "PUBLIC"."TAB" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no grant option for privilege UPDATE on column "ID" of table/view "PUBLIC"."TAB" + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -GRANT failed + -no EXECUTE privilege with grant option on object "PUBLIC"."PAK" +""" + @pytest.mark.version('>=4.0') def test_1(act: Action, user_1, user_2, user_3, role_1, role_2, role_3): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From be632ad000abf4d2c36eff66d55cecab7c9856e0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:37:03 +0300 Subject: [PATCH 0958/1064] Added/Updated tests\bugs\core_5874_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5874_test.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_5874_test.py b/tests/bugs/core_5874_test.py index 2410bb8a..941b5484 100644 --- a/tests/bugs/core_5874_test.py +++ b/tests/bugs/core_5874_test.py @@ -10,6 +10,11 @@ All cases should produce STDERR with specifying table name and R/O column after dot. JIRA: CORE-5874 FBTEST: bugs.core_5874 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -38,7 +43,7 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 attempted update of read-only column TEST.hozzáadása @@ -49,8 +54,20 @@ attempted update of read-only column TEST.hozzáadása """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."hozzáadása" + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."hozzáadása" + + Statement failed, SQLSTATE = 42000 + attempted update of read-only column "PUBLIC"."TEST"."hozzáadása" +""" + @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From db048e7c1291708a5272f4df5ed29bc61eb5d43c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:39:26 +0300 Subject: [PATCH 0959/1064] Added/Updated tests\bugs\core_5876_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5876_test.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_5876_test.py b/tests/bugs/core_5876_test.py index 75682097..4b2b51d8 100644 --- a/tests/bugs/core_5876_test.py +++ b/tests/bugs/core_5876_test.py @@ -19,6 +19,11 @@ in UDR library "udf_compat", see it in folder: ../plugins/udr/ JIRA: CORE-5876 FBTEST: bugs.core_5876 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -87,15 +92,23 @@ def test_1(act_1: Action): act_2 = isql_act('db', test_script_2) -expected_stderr_2 = """ +expected_stderr_5x = """ Statement failed, SQLSTATE = 22012 arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. -At function 'UDR40_DIV' """ +expected_stderr_6x = """ + Statement failed, SQLSTATE = 22012 + arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + -At function "PUBLIC"."UDR40_DIV" +""" + + @pytest.mark.version('>=4.0') def test_2(act_2: Action): - act_2.expected_stderr = expected_stderr_2 + act_2.expected_stderr = expected_stderr_5x if act_2.is_version('<6') else expected_stderr_6x act_2.execute() assert act_2.clean_stderr == act_2.clean_expected_stderr From ec29c560cab184366d534402d090cf90fe9e3b99 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 15:43:34 +0300 Subject: [PATCH 0960/1064] Added/Updated tests\bugs\core_5887_trusted_role_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/core_5887_trusted_role_test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bugs/core_5887_trusted_role_test.py b/tests/bugs/core_5887_trusted_role_test.py index d9e30601..0419c774 100644 --- a/tests/bugs/core_5887_trusted_role_test.py +++ b/tests/bugs/core_5887_trusted_role_test.py @@ -27,6 +27,9 @@ [02.08.2024] pzotov One need to check for admin rights of current OS user (noted by Dimitry Sibiryakov). Checked on Windows 6.0.0.406, 5.0.1.1469, 4.0.5.3139 + [01.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import os @@ -151,6 +154,8 @@ def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys): commit; """ + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' expected_out = f""" MSG point-1 MON$USER {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} @@ -158,7 +163,7 @@ def test_1(act: Action, tmp_role_junior: Role, tmp_role_senior: Role, capsys): MON$REMOTE_PROTOCOL TCP MON$AUTH_METHOD Mapped from Win_Sspi Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST + no permission for SELECT access to TABLE {TABLE_NAME} -Effective user is {THIS_COMPUTER_NAME}\\{CURRENT_WIN_ADMIN.upper()} MSG point-2 From 0f2ed4a0dfa63b524955ad0f9809d6c82a492de3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 20:17:13 +0300 Subject: [PATCH 0961/1064] Added/Updated tests\bugs\core_5905_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5905_test.py | 49 ++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_5905_test.py b/tests/bugs/core_5905_test.py index c95c9161..173d8b00 100644 --- a/tests/bugs/core_5905_test.py +++ b/tests/bugs/core_5905_test.py @@ -19,6 +19,11 @@ (4.x - output phrase "UDF THE_FRAC" instead of "Function THE_FRAC" on attempt to drop function). JIRA: CORE-5905 FBTEST: bugs.core_5905 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -113,6 +118,7 @@ def test_1(act_1: Action): assert (act_1.clean_stderr == act_1.clean_expected_stderr and act_1.clean_stdout == act_1.clean_expected_stdout) +########################################################################## # version: 4.0 test_script_2 = """ @@ -185,40 +191,57 @@ def test_1(act_1: Action): commit; """ -act_2 = isql_act('db', test_script_2) +substitutions = [('[ \t]+', ' ')] +act_2 = isql_act('db', test_script_2, substitutions = substitutions) -expected_stdout_2 = """ +expected_stdout_5x = """ THE_FRAC_1 -0.1415926535897931 - FUNC_NAME THE_FRAC LEGACY_FLAG 0 + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function THE_FRAC + -there are 1 dependencies + FUNC_NAME THE_FRAC LEGACY_FLAG 0 - THE_FRAC_2 7.062513305931052 - THE_FRAC_3 -0.1415926535897931 -""" -expected_stderr_2 = """ Statement failed, SQLSTATE = 38000 unsuccessful metadata update -cannot delete -Function THE_FRAC -there are 1 dependencies +""" + +expected_stdout_6x = """ + THE_FRAC_1 -0.1415926535897931 + FUNC_NAME THE_FRAC + LEGACY_FLAG 0 + + Statement failed, SQLSTATE = 38000 + unsuccessful metadata update + -cannot delete + -Function "PUBLIC"."THE_FRAC" + -there are 1 dependencies + + FUNC_NAME THE_FRAC + LEGACY_FLAG 0 + THE_FRAC_2 7.062513305931052 + THE_FRAC_3 -0.1415926535897931 Statement failed, SQLSTATE = 38000 unsuccessful metadata update -cannot delete - -Function THE_FRAC + -Function "PUBLIC"."THE_FRAC" -there are 1 dependencies """ @pytest.mark.version('>=4.0') def test_2(act_2: Action): - act_2.expected_stdout = expected_stdout_2 - act_2.expected_stderr = expected_stderr_2 - act_2.execute() - assert (act_2.clean_stderr == act_2.clean_expected_stderr and - act_2.clean_stdout == act_2.clean_expected_stdout) + act_2.expected_stdout = expected_stdout_5x if act_2.is_version('<6') else expected_stdout_6x + act_2.execute(combine_output = True) + assert act_2.clean_stdout == act_2.clean_expected_stdout From b32e59a0aeda5fa3fb3b9483b699d84d72186b7d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 20:20:41 +0300 Subject: [PATCH 0962/1064] Added/Updated tests\bugs\core_5965_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5965_test.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/bugs/core_5965_test.py b/tests/bugs/core_5965_test.py index 680e5d6d..51699621 100644 --- a/tests/bugs/core_5965_test.py +++ b/tests/bugs/core_5965_test.py @@ -5,11 +5,16 @@ ISSUE: 6219 TITLE: FB3 Optimiser chooses less efficient plan than FB2.5 optimiser DESCRIPTION: - Filling of database with data from ticket can take noticable time. - Instead of this it was decided to extract form ZIP archieve .fbk and then to restore it. - Instead of actual execution we can only obtain PLAN by querying cursor read-only property "plan" + Filling of database with data from ticket can take noticable time. + Instead of this it was decided to extract from ZIP archieve .fbk and restore it. + Instead of actual execution we can only obtain PLAN by querying cursor read-only property "plan" JIRA: CORE-5965 FBTEST: bugs.core_5965 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -22,11 +27,6 @@ act = python_act('db') -expected_stdout = """ - PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) - PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) -""" - fbk_file = temp_file('core_5965.fbk') @pytest.mark.version('>=3.0') @@ -46,7 +46,17 @@ def test_1(act: Action, fbk_file: Path, db_tmp: Database, capsys): # c2.execute("select 2 from opt_test where sysid = 1 and clid = 23 and cust_type = 1 and cust_id = 73 order by order_no desc") print(c2.statement.plan) - # Check - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) + PLAN SORT (OPT_TEST INDEX (O_CLID_CUSTTY_CUSTID)) + """ + + expected_stdout_6x = """ + PLAN SORT ("PUBLIC"."OPT_TEST" INDEX ("PUBLIC"."O_CLID_CUSTTY_CUSTID")) + PLAN SORT ("PUBLIC"."OPT_TEST" INDEX ("PUBLIC"."O_CLID_CUSTTY_CUSTID")) + """ + + 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 From c666e36e99fcd645fe67bf2f5911ee2322f0cd7f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 20:29:59 +0300 Subject: [PATCH 0963/1064] Added/Updated tests\bugs\core_5970_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_5970_test.py | 1946 ++++++++++++++++------------------ 1 file changed, 893 insertions(+), 1053 deletions(-) diff --git a/tests/bugs/core_5970_test.py b/tests/bugs/core_5970_test.py index 0fe4849d..5bf592be 100644 --- a/tests/bugs/core_5970_test.py +++ b/tests/bugs/core_5970_test.py @@ -10,6 +10,10 @@ Also, it checks that -> encrypt() -> decrypt(encrypted_source) gives the same . JIRA: CORE-5970 FBTEST: bugs.core_5970 +NOTES: + [02.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -328,1060 +332,896 @@ """ -act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) - -expected_stdout = """ - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 11 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 11 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 11 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 11 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 11 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 11 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 11 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 11 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 11 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM AES - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 11 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 12 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 12 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 12 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 12 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 12 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 13 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 13 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 13 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 13 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM ANUBIS - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 13 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 13 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 13 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 13 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 13 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 13 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 15 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 15 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 15 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 15 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM BLOWFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 15 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 14 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 14 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 14 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 14 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 14 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 17 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 17 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 17 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 17 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM KHAZAD - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 17 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 15 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 15 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 15 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 15 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 15 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 19 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 19 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 19 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 19 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC5 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 19 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 17 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 17 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 17 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 17 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 17 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 21 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 21 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 21 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 21 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM RC6 - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 21 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 18 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 18 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 18 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 18 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 18 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 23 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 23 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 23 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 23 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM "SAFER+" - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 23 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 19 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 19 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 19 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 19 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 19 - ENC_INIT_VECTOR_OCTET_LENGTH 16 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 25 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 25 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 25 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 25 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM TWOFISH - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 25 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 20 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 20 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 20 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 20 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 20 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CBC - ENC_KEY_OCTET_LENGTH 26 - ENC_INIT_VECTOR_OCTET_LENGTH 27 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CFB - ENC_KEY_OCTET_LENGTH 26 - ENC_INIT_VECTOR_OCTET_LENGTH 27 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE CTR - ENC_KEY_OCTET_LENGTH 26 - ENC_INIT_VECTOR_OCTET_LENGTH 27 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE ECB - ENC_KEY_OCTET_LENGTH 26 - ENC_INIT_VECTOR_OCTET_LENGTH 27 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545224 - - ENCRYPTION_ALGORITHM XTEA - ENCRYPTION_MODE OFB - ENC_KEY_OCTET_LENGTH 26 - ENC_INIT_VECTOR_OCTET_LENGTH 27 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545229 - - - ENCRYPTION_ALGORITHM CHACHA20 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM CHACHA20 - ENC_KEY_OCTET_LENGTH 21 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545250 - - ENCRYPTION_ALGORITHM CHACHA20 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 29 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545240 - - - ENCRYPTION_ALGORITHM RC4 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 0 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC4 - ENC_KEY_OCTET_LENGTH 22 - ENC_INIT_VECTOR_OCTET_LENGTH 0 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM RC4 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 0 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - - ENCRYPTION_ALGORITHM SOBER128 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE - - ENCRYPTION_ALGORITHM SOBER128 - ENC_KEY_OCTET_LENGTH 23 - ENC_INIT_VECTOR_OCTET_LENGTH 8 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - ENCRYPTION_ALGORITHM SOBER128 - ENC_KEY_OCTET_LENGTH 16 - ENC_INIT_VECTOR_OCTET_LENGTH 33 - ENCRYPTED_EQUALS_TO_DECRYPTED - ENCRYPTION_FINISH_GDSCODE 335545230 - - - CTR_CLAUSE_CASE_2 E813A50C069FC418AA - CTR_CLAUSE_CASE_3 E813A50C069FC418AA - ENCRYPT 8E709DDA89912F172C - ENCRYPT BC3604C147B53D3BDD - ENCRYPT C8051FB1A2581EA9A1 - ENCRYPT 2E2298CF4C2B81AD54 - - INPUT message field count: 0 - - OUTPUT message field count: 3 - 01: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 - : name: ENCRYPT alias: E_BLOB - : table: owner: - 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 255 charset: 1 OCTETS - : name: ENCRYPT alias: E_CHAR - : table: owner: - 03: sqltype: 448 VARYING scale: 0 subtype: 0 len: 6 charset: 1 OCTETS - : name: DECRYPT alias: D_BIN - : table: owner: - -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 22023 - Too big counter value -123, maximum 16 can be used - - Statement failed, SQLSTATE = 22023 - Too big counter value 123, maximum 16 can be used - - Statement failed, SQLSTATE = 22023 - Counter length/value parameter is not used with mode OFB - - Statement failed, SQLSTATE = 22023 - Invalid key length 9, need 16 or 32 -""" +substitutions = [ ('table:.*', '') ] # [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 11 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 11 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 11 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 11 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 11 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 11 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 11 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 11 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 11 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM AES + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 11 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 12 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 12 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 12 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 12 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 12 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 13 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 13 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 13 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 13 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM ANUBIS + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 13 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 13 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 13 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 13 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 13 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 13 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 15 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 15 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 15 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 15 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM BLOWFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 15 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 14 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 14 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 14 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 14 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 14 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 17 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 17 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 17 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 17 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM KHAZAD + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 17 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 15 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 15 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 15 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 15 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 15 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 19 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 19 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 19 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 19 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC5 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 19 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 17 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 17 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 17 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 17 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 17 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 21 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 21 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 21 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 21 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM RC6 + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 21 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 18 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 18 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 18 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 18 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 18 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 23 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 23 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 23 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 23 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM "SAFER+" + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 23 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 19 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 19 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 19 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 19 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 19 + ENC_INIT_VECTOR_OCTET_LENGTH 16 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 25 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 25 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 25 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 25 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM TWOFISH + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 25 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 20 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 20 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 20 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 20 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 20 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CBC + ENC_KEY_OCTET_LENGTH 26 + ENC_INIT_VECTOR_OCTET_LENGTH 27 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CFB + ENC_KEY_OCTET_LENGTH 26 + ENC_INIT_VECTOR_OCTET_LENGTH 27 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE CTR + ENC_KEY_OCTET_LENGTH 26 + ENC_INIT_VECTOR_OCTET_LENGTH 27 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE ECB + ENC_KEY_OCTET_LENGTH 26 + ENC_INIT_VECTOR_OCTET_LENGTH 27 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545224 + ENCRYPTION_ALGORITHM XTEA + ENCRYPTION_MODE OFB + ENC_KEY_OCTET_LENGTH 26 + ENC_INIT_VECTOR_OCTET_LENGTH 27 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545229 + ENCRYPTION_ALGORITHM CHACHA20 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM CHACHA20 + ENC_KEY_OCTET_LENGTH 21 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545250 + ENCRYPTION_ALGORITHM CHACHA20 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 29 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545240 + ENCRYPTION_ALGORITHM RC4 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 0 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC4 + ENC_KEY_OCTET_LENGTH 22 + ENC_INIT_VECTOR_OCTET_LENGTH 0 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM RC4 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 0 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM SOBER128 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE + ENCRYPTION_ALGORITHM SOBER128 + ENC_KEY_OCTET_LENGTH 23 + ENC_INIT_VECTOR_OCTET_LENGTH 8 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + ENCRYPTION_ALGORITHM SOBER128 + ENC_KEY_OCTET_LENGTH 16 + ENC_INIT_VECTOR_OCTET_LENGTH 33 + ENCRYPTED_EQUALS_TO_DECRYPTED + ENCRYPTION_FINISH_GDSCODE 335545230 + Statement failed, SQLSTATE = 22023 + Too big counter value -123, maximum 16 can be used + CTR_CLAUSE_CASE_2 E813A50C069FC418AA + CTR_CLAUSE_CASE_3 E813A50C069FC418AA + Statement failed, SQLSTATE = 22023 + Too big counter value 123, maximum 16 can be used + Statement failed, SQLSTATE = 22023 + Counter length/value parameter is not used with mode OFB + ENCRYPT 8E709DDA89912F172C + ENCRYPT BC3604C147B53D3BDD + ENCRYPT C8051FB1A2581EA9A1 + ENCRYPT 2E2298CF4C2B81AD54 + Statement failed, SQLSTATE = 22023 + Invalid key length 9, need 16 or 32 + INPUT message field count: 0 + OUTPUT message field count: 3 + 01: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 + : name: ENCRYPT alias: E_BLOB + : table: owner: + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 255 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: ENCRYPT alias: E_CHAR + : table: owner: + 03: sqltype: 448 VARYING scale: 0 subtype: 0 len: 6 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: DECRYPT alias: D_BIN + : table: owner: + """ + act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 5f43eb8334c02e8ac6c0893ae4e4fb6978500d5d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 20:36:52 +0300 Subject: [PATCH 0964/1064] Added/Updated tests\bugs\core_5972_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_5972_test.py | 54 ++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/tests/bugs/core_5972_test.py b/tests/bugs/core_5972_test.py index 29bebb97..27bc9def 100644 --- a/tests/bugs/core_5972_test.py +++ b/tests/bugs/core_5972_test.py @@ -21,28 +21,17 @@ 335544382 : COMP 336397208 : At line 1, column 57 Statement : insert into "PERSONS" ("ID", "NAME", "ADDRESS", "INFO", "COMP") values (?, ?, ?, ?, ?) - Data source : Firebird::C:\\FBTESTING\\qa\\misc\\tmprepl.fdb + Data source : Firebird:: -At block line: ... -At trigger 'PERSONS_REPLICATE' We expect appearing of this exception (see try/except block): check its class and content of message. -NOTES: - [08.02.2022] pcisar - Fails on Windows 3.0.8 due to malformed error message: - Got exception: - + Execute statement error at isc_dsql_prepare :335544359 : attempted update of read-only column - - Execute statement error at isc_dsql_prepare : - - 335544359 : attempted update of read-only column - Statement - - Data source - -At block line: 9, col: 5 - -At trigger 'PERSONS_REPLICATE' - [08.04.2022] pzotov - CAN NOT REPRODUCE FAIL! - Test PASSES on FB 3.0.8 Rls, 4.0.1 RLs and 5.0.0.467. - JIRA: CORE-5972 FBTEST: bugs.core_5972 +NOTES: + [02.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -50,10 +39,11 @@ from firebird.qa import * from firebird.driver import DatabaseError -substitutions = [('[ \t]+', ' '), ('.* At block line.*', 'At block'), - ('read-only column.*', 'read-only column'), - ('Statement.*', 'Statement'), ('Data source.*', 'Data source'), - ('.* At trigger.*', 'At trigger')] +substitutions = [ ('[ \t]+', ' '), + ('(-)?At block line.*', 'At block'), + ('read-only column.*', 'read-only column'), + ('Statement.*', 'Statement'), ('Data source.*', 'Data source'), + ] init_script = """ create table persons ( @@ -70,16 +60,6 @@ act = python_act('db', substitutions=substitutions) -expected_stdout = """ - Got exception: - Execute statement error at isc_dsql_prepare : - 335544359 : attempted update of read-only column PERSONS.COMP - Statement : insert into "PERSONS" ("ID", "NAME", "ADDRESS", "INFO", "COMP") values (?, ?, ?, ?, ?) - Data source : Firebird::C:\\FBTESTING\\qa\\fbt-repo\\tmp\\tmp_5972_repl.fdb - -At block line: 9, col: 5 - -At trigger 'PERSONS_REPLICATE' -""" - @pytest.mark.version('>=3.0.6') def test_1(act: Action, db_repl: Database, capsys): ddl_for_replication = f""" @@ -118,6 +98,20 @@ def test_1(act: Action, db_repl: Database, capsys): act.isql(switches=['-q'], input='ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL;') # act.reset() + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TRIGGER_NAME = "'PERSONS_REPLICATE'" if act.is_version('<6') else '"PERSONS_REPLICATE"' + + expected_stdout = f""" + Got exception: + Execute statement error at isc_dsql_prepare : + 335544359 : attempted update of read-only column PERSONS.COMP + Statement : insert into "PERSONS" ("ID", "NAME", "ADDRESS", "INFO", "COMP") values (?, ?, ?, ?, ?) + Data source : Firebird:: + -At block line: 9, col: 5 + -At trigger {SQL_SCHEMA_PREFIX}{TRIGGER_NAME} + """ + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 4308c7493ab2ebe2bb5d8bad24f45dfb37233ad6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 22:30:30 +0300 Subject: [PATCH 0965/1064] Added/Updated tests\bugs\core_6015_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6015_test.py | 46 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/bugs/core_6015_test.py b/tests/bugs/core_6015_test.py index e6e19f79..36e6ea18 100644 --- a/tests/bugs/core_6015_test.py +++ b/tests/bugs/core_6015_test.py @@ -26,6 +26,11 @@ Also, error messages differ because CORE-5606 was not backported to FB 3.x. JIRA: CORE-6015 FBTEST: bugs.core_6015 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -107,43 +112,36 @@ act = isql_act('db', test_script, substitutions=[('(-)?At procedure .*', '')]) -# version: 3.0.8 - -expected_stderr_1 = """ +expected_stdout_3x = """ Statement failed, SQLSTATE = 40001 lock conflict on no wait transaction - -At procedure 'SP_EVAL_STATIC_PSQL' line: 3, col: 8 - At procedure 'SP_EVAL_STATIC_PSQL' line: 3, col: 8 - + Statement failed, SQLSTATE = 40001 Attempt to evaluate index expression recursively - -At procedure 'SP_EVAL_DYNAMIC_SQL' line: 3, col: 8 -lock conflict on no wait transaction """ -@pytest.mark.version('>=3.0.8,<4.0') -def test_1(act: Action): - act.expected_stderr = expected_stderr_1 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr - -# version: 4.0 - -expected_stderr_2 = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Expression evaluation error for index "TEST_STATIC_PSQL_EVAL" on table "TEST_STATIC_PSQL" -Attempt to evaluate index expression recursively - -At procedure 'SP_EVAL_STATIC_PSQL' line: 3, col: 8 - At procedure 'SP_EVAL_STATIC_PSQL' line: 3, col: 8 - Statement failed, SQLSTATE = 42000 Expression evaluation error for index "TEST_DYNAMIC_SQL_EVAL" on table "TEST_DYNAMIC_SQL" -Attempt to evaluate index expression recursively - -At procedure 'SP_EVAL_DYNAMIC_SQL' line: 3, col: 8 """ -@pytest.mark.version('>=4.0') +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Expression evaluation error for index ""PUBLIC"."TEST_STATIC_PSQL_EVAL"" on table ""PUBLIC"."TEST_STATIC_PSQL"" + -Attempt to evaluate index expression recursively + Statement failed, SQLSTATE = 42000 + Expression evaluation error for index ""PUBLIC"."TEST_DYNAMIC_SQL_EVAL"" on table ""PUBLIC"."TEST_DYNAMIC_SQL"" + -Attempt to evaluate index expression recursively +""" + + +@pytest.mark.version('>=3.0') def test_2(act: Action): - act.expected_stderr = expected_stderr_2 - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_3x if act.is_version('<4') else expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1fa9308cb58d063069f40c0962aaf54bae82e81d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 22:34:36 +0300 Subject: [PATCH 0966/1064] Added/Updated tests\bugs\core_6024_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6024_test.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/bugs/core_6024_test.py b/tests/bugs/core_6024_test.py index 2d63363f..1aeeec65 100644 --- a/tests/bugs/core_6024_test.py +++ b/tests/bugs/core_6024_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-6024 FBTEST: bugs.core_6024 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -81,13 +86,19 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN SORT (W INDEX (IXA_WPLATA__KONTRAHENT__PK)) PLAN (W ORDER PK_WPLATA INDEX (IXA_WPLATA__KONTRAHENT__PK)) """ +expected_stdout_6x = """ + PLAN SORT ("W" INDEX ("PUBLIC"."IXA_WPLATA__KONTRAHENT__PK")) + PLAN ("W" ORDER "PUBLIC"."PK_WPLATA" INDEX ("PUBLIC"."IXA_WPLATA__KONTRAHENT__PK")) +""" + @pytest.mark.version('>=3.0.5') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 5f37b88628f3f872abaccba7f792641addd3542d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 23:29:23 +0300 Subject: [PATCH 0967/1064] Added/Updated tests\bugs\core_6044_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6044_test.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_6044_test.py b/tests/bugs/core_6044_test.py index 2233bda5..8d917380 100644 --- a/tests/bugs/core_6044_test.py +++ b/tests/bugs/core_6044_test.py @@ -7,13 +7,19 @@ DESCRIPTION: JIRA: CORE-6044 FBTEST: bugs.core_6044 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 """ import pytest from firebird.qa import * substitutions = [ ('current value.*', 'current value') - ,('COLL-VERSION=\\d+.\\d+(;ICU-VERSION=\\d+.\\d+)?.*', '') + ,("'COLL-VERSION.*", "''") + #,('COLL-VERSION=\\d+.\\d+(;ICU-VERSION=\\d+.\\d+)?.*', '') ] db = db_factory(charset='UTF8') @@ -57,14 +63,16 @@ """ expected_stdout_6x = """ - ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии - ИсключениеДляСообщенияПользователюОНевозможностиПреобразованияя; Msg: Ваша строка не может быть преобразована в число. - КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа, CHARACTER SET UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, ' - ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю - Generator ГенераторКоторыйДолженСодержатьНомераПоследнихУдаленнДокументов, current value - СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю (ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии) VARCHAR(160) CHARACTER SET UTF8 COLLATE КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа Not Null - CONSTRAINT ПервичныйКлючНаТаблицуКотораяВсегдаДолжнаСодержатьСвежайшуюИнфу: - Primary key (СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю) + PUBLIC."ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии" + PUBLIC."ИсключениеДляСообщенияПользователюОНевозможностиПреобразованияя"; Msg: Ваша строка не может быть преобразована в число. + PUBLIC."КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа", CHARACTER SET SYSTEM.UTF8, FROM EXTERNAL ('UNICODE'), PAD SPACE, CASE INSENSITIVE, '' + PUBLIC."ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю" + Generator PUBLIC."ГенераторКоторыйДолженСодержатьНомераПоследнихУдаленнДокументов", current value + Table: PUBLIC."ТаблицаКотораяВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю" + "СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю" (PUBLIC."ДоменДляХраненияСтроковыхДанныхКоторыеПредставимыДляСортировкии") VARCHAR(160) CHARACTER SET SYSTEM.UTF8 COLLATE PUBLIC."КоллацияДляСортировкиСтроковыхДанныхКоторыеПредставимыКакЧислаа" Not Null + CONSTRAINT "ПервичныйКлючНаТаблицуКотораяВсегдаДолжнаСодержатьСвежайшуюИнфу": + Primary key ("СтолбецКоторыйВсегдаДолжнаСодержатьТолькоСамуюСвежуюИнформациюю") + """ @pytest.mark.version('>=4.0') From 72c14b694a5d9120cb82fb38a395327eba432a86 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 23:33:39 +0300 Subject: [PATCH 0968/1064] Added/Updated tests\bugs\core_6049_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 --- tests/bugs/core_6049_test.py | 52 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_6049_test.py b/tests/bugs/core_6049_test.py index 2768f63f..71157505 100644 --- a/tests/bugs/core_6049_test.py +++ b/tests/bugs/core_6049_test.py @@ -5,11 +5,11 @@ ISSUE: 6299 TITLE: Builtin functions converting binary string to hexadecimal representation and vice versa DESCRIPTION: - Test may need to be more complex. Currently only basic operations are checked: - * ability to insert into binary field result of hex_decode() - * result of double conversion: bin_data -> base64_encode -> base64_decode - - must be equal to initial bin_data (and similar for bin_data -> hex_encode -> hex_decode) - We get columns type details using sqlda_display in order to fix them in expected_stdout. + Test may need to be more complex. Currently only basic operations are checked: + * ability to insert into binary field result of hex_decode() + * result of double conversion: bin_data -> base64_encode -> base64_decode + - must be equal to initial bin_data (and similar for bin_data -> hex_encode -> hex_decode) + We get columns type details using sqlda_display in order to fix them in expected_stdout. JIRA: CORE-6049 FBTEST: bugs.core_6049 NOTES: @@ -25,6 +25,10 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. +NOTES: + [02.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 """ import pytest @@ -70,26 +74,28 @@ hex_dec(hex_enc(uid)) result """ -expected_stdout = f""" - 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 20 charset: 1 OCTETS - : name: UID alias: UID - 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 28 charset: 2 ASCII - : name: BASE64_ENCODE alias: b64_encode(uid) - 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 21 charset: 1 OCTETS - : name: BASE64_DECODE alias: b64_decode(b64_encode(uid)) - 04: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 40 charset: 2 ASCII - : name: HEX_ENCODE alias: hex_encode(uid) - 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 20 charset: 1 OCTETS - : name: HEX_DECODE alias: hex_decode(hex_encode(uid)) - 06: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - : name: alias: b64_dec(b64_enc(uid)) result - 07: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 - : name: alias: hex_dec(hex_enc(uid)) result - {COMMON_OUTPUT} -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 20 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: UID alias: UID + 02: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 28 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: BASE64_ENCODE alias: b64_encode(uid) + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 21 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: BASE64_DECODE alias: b64_decode(b64_encode(uid)) + 04: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 40 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: HEX_ENCODE alias: hex_encode(uid) + 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 20 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: HEX_DECODE alias: hex_decode(hex_encode(uid)) + 06: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 + : name: alias: b64_dec(b64_enc(uid)) result + 07: sqltype: 32764 BOOLEAN Nullable scale: 0 subtype: 0 len: 1 + : name: alias: hex_dec(hex_enc(uid)) result + {COMMON_OUTPUT} + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 7867fed25aa4ceb24898acda76936d8de97b5f0a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 23:44:38 +0300 Subject: [PATCH 0969/1064] Added/Updated tests\bugs\core_6054_test.py: Refactored: added subst to suppress name of non-existing column as it has no matter for this test. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6054_test.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/bugs/core_6054_test.py b/tests/bugs/core_6054_test.py index 89f83ada..b429bb56 100644 --- a/tests/bugs/core_6054_test.py +++ b/tests/bugs/core_6054_test.py @@ -5,8 +5,15 @@ ISSUE: 6304 TITLE: Random crash 64bit fb_inet_server. Possible collation issue DESCRIPTION: + Only *one* error message should raise. + Output should finish on: 'Records affected: 0', see: + https://github.com/FirebirdSQL/firebird/issues/6304#issuecomment-826244780 JIRA: CORE-6054 FBTEST: bugs.core_6054 +NOTES: + [02.07.2025] pzotov + Refactored: added subst to suppress name of non-existing column as it has no matter for this test. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -16,32 +23,26 @@ test_script = """ recreate table c (id int, f1 varchar(32) character set win1251 collate win1251); - select * from c where f2 collate win1251_ua = 'x'; + select * from c where non_existing_column collate win1251_ua = 'x'; set count on; select * from c where f1 = _utf8 'x'; """ -act = isql_act('db', test_script, - substitutions=[('-At line[:]{0,1}[\\s]+[\\d]+,[\\s]+column[:]{0,1}[\\s]+[\\d]+', - '-At line: column:')]) +substitutions = [('(-)?At line.*', ''), ('(-)?(")?NON_EXISTING_COLUMN(")?', '')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - Records affected: 0 -""" - -expected_stderr = """ Statement failed, SQLSTATE = 42S22 Dynamic SQL Error -SQL error code = -206 -Column unknown - -F2 - -At line: column: + + Records affected: 0 """ @pytest.mark.version('>=2.5.9') def test_1(act: Action): + act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From f181072fd842f223d0edafaf07681569cdaedc4b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Wed, 2 Jul 2025 23:48:32 +0300 Subject: [PATCH 0970/1064] Added/Updated tests\bugs\core_6078_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6078_test.py | 133 +++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_6078_test.py b/tests/bugs/core_6078_test.py index 6df20b30..4620bb2b 100644 --- a/tests/bugs/core_6078_test.py +++ b/tests/bugs/core_6078_test.py @@ -10,6 +10,11 @@ privilege to do this. JIRA: CORE-6078 FBTEST: bugs.core_6078 +NOTES: + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -189,9 +194,11 @@ def test_1(act: Action, user_0: User, user_1: User, user_2: User): act.isql(switches=['-q'], input=script, combine_output=True) assert act.clean_stdout == act.clean_expected_stdout -# version: 4.0 +############################################################################ -expected_stdout_2 = """ +# version: 4.0+ + +expected_stdout_5x = """ Statement failed, SQLSTATE = 28000 modify record error -no permission for UPDATE access to COLUMN PLG$SRP_VIEW.PLG$ACTIVE @@ -346,6 +353,123 @@ def test_1(act: Action, user_0: User, user_1: User, user_2: User): -System privilege CHANGE_MAPPING_RULES is missing """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 28000 + modify record error + -no permission for UPDATE access to COLUMN "PLG$SRP"."PLG$SRP_VIEW"."PLG$ACTIVE" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DATABASE failed + -no permission for ALTER access to DATABASE + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER DOMAIN "PUBLIC"."DM_TEST" failed + -no permission for ALTER access to DOMAIN "PUBLIC"."DM_TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE "PUBLIC"."TEST" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER INDEX "PUBLIC"."TEST_UID" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -COMMENT ON "PUBLIC"."TEST" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER "PUBLIC"."TEST_BI" failed + -no permission for ALTER access to TABLE "PUBLIC"."TEST" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER "PUBLIC"."TRG$START" failed + -no permission for ALTER access to DATABASE + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE OR ALTER TRIGGER "PUBLIC"."TRIG_DDL_SP" failed + -no permission for ALTER access to DATABASE + ALTERED_TRIGGER_NAME TEST_BI + ALTERED_TRIGGER_SOURCE + as + begin + new.uid = gen_uuid(); + end + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PACKAGE "PUBLIC"."PKG_TEST" failed + -No permission for CREATE PACKAGE operation + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -RECREATE PACKAGE BODY "PUBLIC"."PKG_TEST" failed + -No permission for CREATE PACKAGE operation + ALTERED_PKG_NAME + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER FUNCTION "PUBLIC"."FN_C6078" failed + -No permission for CREATE FUNCTION operation + ALTERED_STANDALONE_FUNC + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."SP_C6078" failed + -No permission for CREATE PROCEDURE operation + ALTERED_STANDALONE_PROC + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER VIEW "PUBLIC"."V_C6078" failed + -No permission for CREATE VIEW operation + ALTERED_VIEW_NAME + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -ALTER SEQUENCE "PUBLIC"."SQ_C6078" failed + -No permission for CREATE GENERATOR operation + ALTERED_SEQUENCE_NAME + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER EXCEPTION "PUBLIC"."EX_C6078" failed + -No permission for CREATE EXCEPTION operation + ALTERED_EXCEPTION_NAME + Records affected: 1 + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER FUNCTION "PUBLIC"."WAIT_EVENT" failed + -No permission for CREATE FUNCTION operation + ALTERED_UDR_BASED_FUNC + Records affected: 1 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER CHARACTER SET "SYSTEM"."UTF8" failed + -no permission for ALTER access to CHARACTER SET "SYSTEM"."UTF8" + -Effective user is TMP$C6078_0 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER MAPPING LOCAL_MAP_C6078 failed + -Unable to perform operation + -System privilege CHANGE_MAPPING_RULES is missing + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER MAPPING GLOBAL_MAP_C6078 failed + -Unable to perform operation + -System privilege CHANGE_MAPPING_RULES is missing +""" + @pytest.mark.version('>=4.0') def test_2(act: Action, user_0: User, user_1: User, user_2: User): script_vars = {'dsn': act.db.dsn, @@ -353,6 +477,7 @@ def test_2(act: Action, user_0: User, user_1: User, user_2: User): 'user_password': act.db.password,} script_file = act.files_dir / 'core_6078.sql' script = script_file.read_text() % script_vars - act.expected_stdout = expected_stdout_2 - act.isql(switches=['-q'], input=script, combine_output=True) + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], input = script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 9ee88fe759dd393ec29247fab0e185aa2e751fd2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:10:26 +0300 Subject: [PATCH 0971/1064] Added/Updated tests\bugs\core_6160_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 --- tests/bugs/core_6160_test.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_6160_test.py b/tests/bugs/core_6160_test.py index 642c2068..cda2e18c 100644 --- a/tests/bugs/core_6160_test.py +++ b/tests/bugs/core_6160_test.py @@ -17,6 +17,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [03.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 """ import pytest @@ -34,14 +37,16 @@ act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|charset).)*$', ''), ('[ \t]+', ' '), ('.*charset: [\\d]+', 'charset:')]) - -expected_stdout = """ - charset: ASCII - charset: ASCII -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + charset: {SQL_SCHEMA_PREFIX}ASCII + charset: {SQL_SCHEMA_PREFIX}ASCII + """ + + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From d366cd614251efd8d9a66489696195912781d951 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:10:51 +0300 Subject: [PATCH 0972/1064] Added/Updated tests\bugs\core_6049_test.py: minor change: removed duplicates 'notes:' record --- tests/bugs/core_6049_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/bugs/core_6049_test.py b/tests/bugs/core_6049_test.py index 71157505..c76444dc 100644 --- a/tests/bugs/core_6049_test.py +++ b/tests/bugs/core_6049_test.py @@ -25,7 +25,6 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. -NOTES: [02.07.2025] pzotov Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 From 68356716d675d0f621f12f06e4f36953303b6c5e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:15:07 +0300 Subject: [PATCH 0973/1064] Added/Updated tests\bugs\core_6166_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6166_test.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/bugs/core_6166_test.py b/tests/bugs/core_6166_test.py index 97fb1982..5659cbae 100644 --- a/tests/bugs/core_6166_test.py +++ b/tests/bugs/core_6166_test.py @@ -14,6 +14,11 @@ of max allowed len (63 characters). JIRA: CORE-6166 FBTEST: bugs.core_6166 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -23,13 +28,6 @@ act = python_act('db') -expected_stdout = """ - ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений - КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ UNIQUE INDEX ON КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений(КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений) - МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений 123 - МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений 456 -""" - ddl_script = """ set term ^; recreate package "ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений" as @@ -79,9 +77,26 @@ @pytest.mark.intl @pytest.mark.version('>=4.0') def test_1(act: Action): + + expected_stdout_5x = """ + ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений + КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ UNIQUE INDEX ON КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений(КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений, КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений) + МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений 123 + МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений 456 + """ + + expected_stdout_6x = """ + PUBLIC."ПакетДляРешенияЛинейныхГиперболическихИТрансцендентныхУравнений" + PUBLIC."КоэффициентыЛинейныхГиперболическихИТрансцендентныхУравненийЦЫЧ" UNIQUE INDEX ON "КоэффициентыДляЛинейныхГиперболическихИТрансцендентныхУравнений"("КоэффициентЦДляЛинейныхГиперболическихИТрансцендентныхУравнений", "КоэффициентЫДляЛинейныхГиперболическихИТрансцендентныхУравнений", "КоэффициентЧДляЛинейныхГиперболическихИТрансцендентныхУравнений") + МетодЗейделяДляЛинейныхГиперболическихИТрансцендентныхУравнений 123 + МетодНьютонаДляЛинейныхГиперболическихИТрансцендентныхУравнений 456 + """ + expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.expected_stdout = expected_stdout act.isql(switches=[], input=ddl_script + test_script, charset='utf8') assert act.clean_stdout == act.clean_expected_stdout + # Extract metadata act.reset() act.isql(switches=['-x'], charset='utf8') @@ -92,6 +107,7 @@ def test_1(act: Action): # Recereate metadata act.reset() act.isql(switches=[], input=meta, charset='utf8') + # Check 2 act.reset() act.expected_stdout = expected_stdout From 925b4ce1ba8caad14c00e138e86c4201efe1979f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:16:36 +0300 Subject: [PATCH 0974/1064] Added/Updated tests\bugs\core_6171_test.py: Removed 'set plan on' because it has no matter for this test --- tests/bugs/core_6171_test.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/bugs/core_6171_test.py b/tests/bugs/core_6171_test.py index 6332ac56..fe92901d 100644 --- a/tests/bugs/core_6171_test.py +++ b/tests/bugs/core_6171_test.py @@ -37,8 +37,6 @@ commit; set heading off; - set plan on; - select r.s from tmain r where @@ -55,9 +53,6 @@ act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) expected_stdout = """ - PLAN (D NATURAL) - PLAN (R NATURAL) - foo bar rio @@ -67,5 +62,5 @@ @pytest.mark.version('>=3.0.5') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ad7eaeffae98264460d42d12e47be4aee59ecc16 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:21:41 +0300 Subject: [PATCH 0975/1064] Added/Updated tests\bugs\core_6218_test.py: Removed 'set plan on' because it has no matter for this test. Difference of transactions before and after queries must be checked to be sure that there was no crash. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6218_test.py | 46 ++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_6218_test.py b/tests/bugs/core_6218_test.py index ed5b8610..a88195a2 100644 --- a/tests/bugs/core_6218_test.py +++ b/tests/bugs/core_6218_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-6218 FBTEST: bugs.core_6218 +NOTES: + [03.07.2025] pzotov + Difference of transactions before and after queries must be checked to be sure that there was no crash. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -15,6 +19,7 @@ db = db_factory() test_script = """ + set list on; recreate table test(n decfloat); commit; @@ -22,43 +27,32 @@ insert into test values( 0 ); commit; - set list on; - set explain on; + set term ^; + execute block as + begin + rdb$set_context('USER_TRANSACTION', 'INIT_TX', current_transaction); + end ^ + set term ;^ select n as n_grouped_from_test0 from test group by 1; --- [ 1 ] select distinct n as n_uniq_from_test0 from test; -- [ 2 ] select count(distinct n) as count_uniq_from_test0 from test; -- [ 3 ] + select current_transaction - cast( rdb$get_context('USER_TRANSACTION', 'INIT_TX') as int) as tx_diff from rdb$database; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) expected_stdout = """ - Select Expression - -> Aggregate - -> Sort (record length: 68, key length: 24) - -> Table "TEST" Full Scan - - N_GROUPED_FROM_TEST0 0 - - - - Select Expression - -> Unique Sort (record length: 68, key length: 24) - -> Table "TEST" Full Scan - - N_UNIQ_FROM_TEST0 0 - - - - Select Expression - -> Aggregate - -> Table "TEST" Full Scan - - COUNT_UNIQ_FROM_TEST0 1 + N_GROUPED_FROM_TEST0 0 + N_UNIQ_FROM_TEST0 0 + COUNT_UNIQ_FROM_TEST0 1 + TX_DIFF 0 """ @pytest.mark.version('>=4.0') def test_1(act: Action): + act.expected_stdout = expected_stdout - act.execute() + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 3c2c3fe5a3cdbdef1219c56344905b9c608c72be Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:24:24 +0300 Subject: [PATCH 0976/1064] Added/Updated tests\bugs\core_6239_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6239_test.py | 53 ++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/tests/bugs/core_6239_test.py b/tests/bugs/core_6239_test.py index 39e436ef..0e6c2ba6 100644 --- a/tests/bugs/core_6239_test.py +++ b/tests/bugs/core_6239_test.py @@ -8,8 +8,14 @@ JIRA: CORE-6239 FBTEST: bugs.core_6239 NOTES: - Fix was done by commit https://github.com/FirebirdSQL/firebird/commit/b2b5f9a87cea26a9f12fa231804dba9d0426d3fa - (can be checked by 4.0.0.1763+, date of build since 05-feb-2020). + [05.02.2020] pzotov + Fix was done by commit https://github.com/FirebirdSQL/firebird/commit/b2b5f9a87cea26a9f12fa231804dba9d0426d3fa + (can be checked by 4.0.0.1763+, date of build since 05-feb-2020). + + [02.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -94,7 +100,7 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 Dynamic SQL Error -SQL error code = -104 @@ -134,8 +140,43 @@ -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + Statement failed, SQLSTATE = 42000 + Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."SP_MISSED_RETURNS_IN_ITS_HEADER_1" failed + -Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."SP_MISSED_RETURNS_IN_ITS_HEADER_2" failed + -Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE OR ALTER PROCEDURE "PUBLIC"."SP_MISSED_RETURNS_IN_ITS_HEADER_3" failed + -Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -CREATE PACKAGE BODY "PUBLIC"."PG_TEST_1" failed + -Dynamic SQL Error + -SQL error code = -104 + -SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK +""" + @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 787ab191adecdc042c6c0e1b5e620971a119cd7a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:28:33 +0300 Subject: [PATCH 0977/1064] Added/Updated tests\bugs\core_6252_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_6252_test.py | 64 +++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/tests/bugs/core_6252_test.py b/tests/bugs/core_6252_test.py index 55cb1be5..ded946f3 100644 --- a/tests/bugs/core_6252_test.py +++ b/tests/bugs/core_6252_test.py @@ -8,6 +8,11 @@ DESCRIPTION: JIRA: CORE-6252 FBTEST: bugs.core_6252 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -69,37 +74,50 @@ ; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ - A 1 - B 1 - A 1 - B 2 - - U 1 - V 1 - U 1 - V 1 - - IDX_NAME - IDX_UNIQ -""" - -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 23000 violation of PRIMARY or UNIQUE KEY constraint "TEST1_UNQ" on table "TEST1" -Problematic key value is ("A" = 1) - Statement failed, SQLSTATE = 23000 violation of PRIMARY or UNIQUE KEY constraint "TEST2_PK" on table "TEST2" -Problematic key value is ("U" = 1) + A 1 + B 1 + A 1 + B 2 + U 1 + V 1 + U 1 + V 1 + IDX_NAME + IDX_UNIQ +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST1_UNQ" on table "PUBLIC"."TEST1" + -Problematic key value is ("A" = 1) + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "TEST2_PK" on table "PUBLIC"."TEST2" + -Problematic key value is ("U" = 1) + A 1 + B 1 + A 1 + B 2 + U 1 + V 1 + U 1 + V 1 + IDX_NAME + IDX_UNIQ """ @pytest.mark.version('>=3.0.6') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 679900b0c619f8085213d4d2e3444571d2ba6eec Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:31:49 +0300 Subject: [PATCH 0978/1064] Added/Updated tests\bugs\core_6278_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 --- tests/bugs/core_6278_test.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_6278_test.py b/tests/bugs/core_6278_test.py index 982722fa..4aa4e4f9 100644 --- a/tests/bugs/core_6278_test.py +++ b/tests/bugs/core_6278_test.py @@ -14,15 +14,17 @@ into a table: smaller values of RDB$DB_KEY can appear *after* bigger ones (i.e. smaller RDB$DB_KEY will be physically closer to the end of table than bigger). Because of that, we check only EXPLAINED PLAN, without runtime statistics from trace log before. - On build 4.0.0.1865 (07-apr-2020) explained plan for scoped query (like 'rdb$db_key between ? and ?') returned "Table ... Full Scan" - WITHOUT "(lower bound, upper bound)". - Since build 4.0.0.1869 (08-apr-2020) this opewration is: "Table "TEST" Full Scan (lower bound, upper bound)". See commit: https://github.com/FirebirdSQL/firebird/commit/3ce4605e3cc9960afcf0224ea40e04f508669eca - Checked on 5.0.1.1394, 6.0.0.345. + + [03.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214. + """ import pytest @@ -57,42 +59,43 @@ def test_1(act: Action, capsys): with cur.prepare(f'select count(s) from test where {x}') as ps: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan .split('\n')]) ) - - act.expected_stdout = """ + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + act.expected_stdout = f""" Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (lower bound, upper bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (lower bound, upper bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (lower bound, upper bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (lower bound, upper bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (lower bound, upper bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (lower bound, upper bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (lower bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (lower bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (lower bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (lower bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (upper bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (upper bound) Select Expression ....-> Aggregate ........-> Filter - ............-> Table "TEST" Full Scan (upper bound) + ............-> Table {SQL_SCHEMA_PREFIX}"TEST" Full Scan (upper bound) """ + act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 5b71031de13ca13f060067adacb6c038d8d67f1f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 00:34:46 +0300 Subject: [PATCH 0979/1064] Added/Updated tests\bugs\core_6285_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6285_test.py | 70 +++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/tests/bugs/core_6285_test.py b/tests/bugs/core_6285_test.py index deb5aebe..76b40507 100644 --- a/tests/bugs/core_6285_test.py +++ b/tests/bugs/core_6285_test.py @@ -12,6 +12,11 @@ 'INCLUDE ...' and 'EXCLUDE ...' respectively (after reply from dimitr). JIRA: CORE-6285 FBTEST: bugs.core_6285 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -58,9 +63,10 @@ select 'rdb$pub after DROP LIST of some tables from publication' as msg, p.* from rdb$database left join RDB$PUBLICATION_TABLES p on 1=1; """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ MSG rdb$pub: initial content for a NEW database RDB$PUBLICATION_NAME RDB$DEFAULT RDB$OWNER_NAME SYSDBA @@ -116,8 +122,64 @@ Records affected: 1 """ +expected_stdout_6x = """ + MSG rdb$pub: initial content for a NEW database + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$OWNER_NAME SYSDBA + RDB$SYSTEM_FLAG 1 + RDB$ACTIVE_FLAG 0 + RDB$AUTO_ENABLE 0 + Records affected: 1 + MSG rdb$pub after enable for the WHOLE DATABASE + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$OWNER_NAME SYSDBA + RDB$SYSTEM_FLAG 1 + RDB$ACTIVE_FLAG 1 + RDB$AUTO_ENABLE 0 + Records affected: 1 + MSG rdb$pub after disable for the WHOLE DATABASE + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$OWNER_NAME SYSDBA + RDB$SYSTEM_FLAG 1 + RDB$ACTIVE_FLAG 0 + RDB$AUTO_ENABLE 0 + Records affected: 1 + MSG rdb$pub after ADD ALL tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST1 + RDB$TABLE_SCHEMA_NAME PUBLIC + MSG rdb$pub after ADD ALL tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST2 + RDB$TABLE_SCHEMA_NAME PUBLIC + MSG rdb$pub after ADD ALL tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST3 + RDB$TABLE_SCHEMA_NAME PUBLIC + Records affected: 3 + MSG rdb$pub after DROP ALL tables from publication + RDB$PUBLICATION_NAME + RDB$TABLE_NAME + RDB$TABLE_SCHEMA_NAME + Records affected: 1 + MSG rdb$pub after ADD LIST of some tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST2 + RDB$TABLE_SCHEMA_NAME PUBLIC + MSG rdb$pub after ADD LIST of some tables to publication + RDB$PUBLICATION_NAME RDB$DEFAULT + RDB$TABLE_NAME TEST3 + RDB$TABLE_SCHEMA_NAME PUBLIC + Records affected: 2 + MSG rdb$pub after DROP LIST of some tables from publication + RDB$PUBLICATION_NAME + RDB$TABLE_NAME + RDB$TABLE_SCHEMA_NAME + Records affected: 1 +""" + @pytest.mark.version('>=4.0.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 0d6793ad2e99fd4416b6142284ab124cf7d43b84 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 13:39:39 +0300 Subject: [PATCH 0980/1064] Added/Updated tests\bugs\core_0203_test.py: Re-implemented: use explained form of plans for check. Output is organized to be more suitable for reading and search for mismatches (see 'qry_map' dict). Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_0203_test.py | 505 +++++++++++++++++++++++++++++------ 1 file changed, 428 insertions(+), 77 deletions(-) diff --git a/tests/bugs/core_0203_test.py b/tests/bugs/core_0203_test.py index 30afd700..fcc9b6e0 100644 --- a/tests/bugs/core_0203_test.py +++ b/tests/bugs/core_0203_test.py @@ -5,36 +5,32 @@ ISSUE: 530 TITLE: CREATE VIEW ignores PLAN DESCRIPTION: -Test verifies that: -1. "PLAN <...>" clause inside view DLL is always ignored and actual plan will be one of following: - 1.1. That is specified explicitly by client who runs a query to this view; - 1.2. If no explicitly specified plan that optimizer will be allowed to choose that. -2. One may to specify PLAN on client side and it *WILL* be taken in account. -NOTES: -Suppose that some view contains explicitly specified PLAN NATURAL it its DDL. -If underlying query became suitable to be run with PLAN INDEX (e.g. such index was added to the table) -then this 'PLAN NATURAL' will be IGNORED until it is explicitly specified in the client query. -See below example #4 for view v_test1 defined as "select * from ... plan (t natural)". + Test verifies that: + 1. "PLAN <...>" clause inside view DLL is always ignored and actual plan will be one of following: + 1.1. That is specified explicitly by client who runs a query to this view; + 1.2. If no explicitly specified plan that optimizer will be allowed to choose that. + 2. One may to specify PLAN on client side and it *WILL* be taken in account. + + It is supposed that some view contains explicitly specified PLAN NATURAL it its DDL. + If underlying query became suitable to be run with PLAN INDEX (e.g. such index was added to the table) + then this 'PLAN NATURAL' will be IGNORED until it is explicitly specified in the client query. + See below example #4 for view v_test1 defined as "select * from ... plan (t natural)". JIRA: CORE-203 FBTEST: bugs.core_0203 NOTES: - [22.06.2025] *** DEFERRED ***, SEE LETTER TO DIMITR AND ADRIANO. - https://github.com/FirebirdSQL/firebird/issues/8623 + [03.07.2025] pzotov + Re-implemented: use explained form of plans for check. + Output is organized to be more suitable for reading and search for mismatches (see 'qry_map' dict). + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214. """ import pytest from firebird.qa import * -db = db_factory() - -test_script = """ +init_script = """ set bail on; - - recreate view v_test4 as select 1 x from rdb$database; - recreate view v_test3 as select 1 x from rdb$database; - recreate view v_test2 as select 1 x from rdb$database; - recreate view v_test1 as select 1 x from rdb$database; - recreate table test(x int, y int); commit; @@ -57,69 +53,424 @@ recreate view v_test3 as select * from test t where x = 0 plan (t index(test_x_desc)); recreate view v_test4 as select * from v_test3; commit; - - - SET BAIL ON; - SET ECHO ON; - set planonly; - - select * from test t where x = 0 plan (t natural); -- 1 - - select * from v_test1 v1; -- 2 - - select * from v_test1 v2; -- 3 - - select * from v_test1 v1 where v1.x = 0 plan (v1 natural); -- 4 - - select * from v_test2 v2 where v2.x = 0 plan (v2 natural); -- 5 - - select * from v_test1 v1 where v1.x = 0 PLAN (V1 INDEX (TEST_X_DESC)) ; -- 6 - - select * from v_test2 v2 where v2.x = 0 PLAN (V2 INDEX (TEST_X_DESC)) ; -- 7 - - select * from v_test1 v1 where v1.x = 50 and v1.y = 5000 PLAN (V1 INDEX (test_x_y)) ; -- 8 - - select * from v_test1 v2 where v2.x = 50 and v2.y = 5000 PLAN (V2 INDEX (test_y_x)) ; -- 9 - - select * from v_test1 v1 where v1.x + v1.y = 1000 PLAN (V1 INDEX (test_x_y)); -- 10 - - select * from v_test2 v2 where v2.x - v2.y = 1000 PLAN (V2 INDEX (test_x_y)); -- 11 - - select * from v_test1 v1 where v1.x + v1.y = 1000 PLAN (V1 INDEX (test_sum_x_y)); -- 12 - - select * from v_test2 v2 where v2.x - v2.y = 1000 PLAN (V2 INDEX (test_sub_x_y)); -- 13 - - -- NB: here optimizer will use index __NOT__ from view V3 DDL: - -- PLAN (V3 T INDEX (TEST_X_ASC)) - select * from v_test3 v3; -- 14 - - select * from v_test3 v3 plan ( v3 index(test_x_y) ); - - -- NB: here optimizer will use index __NOT__ from view V3 DDL: - -- PLAN (V4 V_TEST3 T INDEX (TEST_X_ASC)) - select * from v_test4 v4; -- 15 - - select * from v_test4 v4 PLAN (V4 V_TEST3 T INDEX (TEST_X_Y)); -- 16 """ -# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings -# from act.files_dir/'test_config.ini': -# -addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress'] -addi_subst_tokens = addi_subst_settings['addi_subst'] + +db = db_factory(init = init_script) substitutions = [('[ \t]+', ' ')] -#for p in addi_subst_tokens.split(' '): -# substitutions.append( (p, '') ) +act = isql_act('db', substitutions = substitutions) -act = isql_act('db', test_script, substitutions = substitutions) +#----------------------------------------------------------- -expected_stdout = """ -""" +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- @pytest.mark.version('>=3') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() +def test_1(act: Action, capsys): + + qry_map = { + 1 : ( 'select * from test t where x = 0 plan (t natural)', '' ) + , 2 : ( 'select * from v_test1 v1', '' ) + , 3 : ( 'select * from v_test1 v2', '' ) + , 4 : ( 'select * from v_test1 v1 where v1.x = 0 plan (v1 natural)', '' ) + , 5 : ( 'select * from v_test2 v2 where v2.x = 0 plan (v2 natural)', '' ) + , 6 : ( 'select * from v_test1 v1 where v1.x = 0 PLAN (V1 INDEX (TEST_X_DESC))', '' ) + , 7 : ( 'select * from v_test2 v2 where v2.x = 0 PLAN (V2 INDEX (TEST_X_DESC))', '' ) + , 8 : ( 'select * from v_test1 v1 where v1.x = 50 and v1.y = 5000 PLAN (V1 INDEX (test_x_y))', '' ) + , 9 : ( 'select * from v_test1 v2 where v2.x = 50 and v2.y = 5000 PLAN (V2 INDEX (test_y_x))', '' ) + ,10 : ( 'select * from v_test1 v1 where v1.x + v1.y = 1000 PLAN (V1 INDEX (test_x_y))', '' ) + ,11 : ( 'select * from v_test2 v2 where v2.x - v2.y = 1000 PLAN (V2 INDEX (test_x_y))', '' ) + ,12 : ( 'select * from v_test1 v1 where v1.x + v1.y = 1000 PLAN (V1 INDEX (test_sum_x_y))', '' ) + ,13 : ( 'select * from v_test2 v2 where v2.x - v2.y = 1000 PLAN (V2 INDEX (test_sub_x_y))', '' ) + ,14 : ( 'select * from v_test3 v3', 'must use index TEST_X_ASC' ) + ,15 : ( 'select * from v_test3 v3 plan ( v3 index(test_x_y) )', '' ) + ,16 : ( 'select * from v_test4 v4', 'must use index TEST_X_ASC' ) + ,17 : ( 'select * from v_test4 v4 PLAN (V4 V_TEST3 T INDEX (TEST_X_Y))', '' ) + } + for qry_idx,v in qry_map.items(): + qry_comment = f'{qry_idx=} ' + v[1] + qry_map[qry_idx] = (v[0], qry_comment) + + + with act.db.connect() as con: + cur = con.cursor() + for qry_idx, qry_data in qry_map.items(): + test_sql, qry_comment = qry_data[:2] + ps, rs = None, None + try: + cur = con.cursor() + ps = cur.prepare(test_sql) + + print(qry_comment) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + + expected_stdout_3x = f""" + {qry_map[ 1][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "T" Full Scan + + {qry_map[ 2][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[ 3][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[ 4][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V1 T" Full Scan + + {qry_map[ 5][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Full Scan + + {qry_map[ 6][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V1 T" Access By ID + ................-> Bitmap + ....................-> Index "TEST_X_DESC" Range Scan (full match) + + {qry_map[ 7][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DESC" Range Scan (full match) + + {qry_map[ 8][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V1 T" Access By ID + ................-> Bitmap + ....................-> Index "TEST_X_Y" Range Scan (full match) + + {qry_map[ 9][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V2 T" Access By ID + ................-> Bitmap + ....................-> Index "TEST_Y_X" Range Scan (full match) + + {qry_map[10][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V1 T" Access By ID + ................-> Bitmap + ....................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[11][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[12][1]} + Select Expression + ....-> Filter + ........-> Filter + ............-> Table "TEST" as "V1 T" Access By ID + ................-> Bitmap + ....................-> Index "TEST_SUM_X_Y" Range Scan (full match) + + {qry_map[13][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_SUB_X_Y" Range Scan (full match) + + {qry_map[14][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[15][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[16][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V4 V_TEST3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[17][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V4 V_TEST3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + """ + + expected_stdout_5x = f""" + {qry_map[ 1][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "T" Full Scan + + {qry_map[ 2][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[ 3][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[ 4][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Full Scan + + {qry_map[ 5][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Full Scan + + {qry_map[ 6][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DESC" Range Scan (full match) + + {qry_map[ 7][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_DESC" Range Scan (full match) + + {qry_map[ 8][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (full match) + + {qry_map[ 9][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_Y_X" Range Scan (full match) + + {qry_map[10][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[11][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[12][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V1 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_SUM_X_Y" Range Scan (full match) + + {qry_map[13][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V2 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_SUB_X_Y" Range Scan (full match) + + {qry_map[14][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[15][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[16][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V4 V_TEST3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_ASC" Range Scan (full match) + + {qry_map[17][1]} + Select Expression + ....-> Filter + ........-> Table "TEST" as "V4 V_TEST3 T" Access By ID + ............-> Bitmap + ................-> Index "TEST_X_Y" Range Scan (partial match: 1/2) + + """ + + expected_stdout_6x = f""" + {qry_map[ 1][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "T" Full Scan + + {qry_map[ 2][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + + {qry_map[ 3][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + + {qry_map[ 4][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Full Scan + + {qry_map[ 5][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Full Scan + + {qry_map[ 6][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_DESC" Range Scan (full match) + + {qry_map[ 7][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_DESC" Range Scan (full match) + + {qry_map[ 8][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_Y" Range Scan (full match) + + {qry_map[ 9][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_Y_X" Range Scan (full match) + + {qry_map[10][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[11][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[12][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V1" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_SUM_X_Y" Range Scan (full match) + + {qry_map[13][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V2" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_SUB_X_Y" Range Scan (full match) + + {qry_map[14][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V3" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + + {qry_map[15][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V3" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_Y" Range Scan (partial match: 1/2) + + {qry_map[16][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V4" "PUBLIC"."V_TEST3" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + + {qry_map[17][1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" as "V4" "PUBLIC"."V_TEST3" "T" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_Y" Range Scan (partial match: 1/2) + """ + + act.expected_stdout = expected_stdout_3x if act.is_version('<5') else 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 From d0a9bbf4d560ed92bbf46045c674e5f7140c2b5e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 13:47:39 +0300 Subject: [PATCH 0981/1064] Added/Updated tests\bugs\core_6300_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6300_test.py | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/tests/bugs/core_6300_test.py b/tests/bugs/core_6300_test.py index a8587983..a3e03748 100644 --- a/tests/bugs/core_6300_test.py +++ b/tests/bugs/core_6300_test.py @@ -15,6 +15,12 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. + """ import pytest @@ -31,23 +37,25 @@ act = isql_act('db', test_script, substitutions = [ ( '^((?!SQLSTATE|sqltype|name:).)*$', ''), ('[ \t]+', ' ') ] ) -expected_stdout = """ - 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 38 charset: 0 NONE - : name: MON$GUID alias: MON$GUID - 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 255 charset: 2 ASCII - : name: MON$FILE_ID alias: MON$FILE_ID - 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: MON$NEXT_ATTACHMENT alias: MON$NEXT_ATTACHMENT - 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: MON$NEXT_STATEMENT alias: MON$NEXT_STATEMENT - 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 NONE - : name: RDB$GET_CONTEXT alias: RDB$GET_CONTEXT - 06: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 NONE - : name: RDB$GET_CONTEXT alias: RDB$GET_CONTEXT -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 38 charset: 0 {SQL_SCHEMA_PREFIX}NONE + : name: MON$GUID alias: MON$GUID + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 255 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: MON$FILE_ID alias: MON$FILE_ID + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: MON$NEXT_ATTACHMENT alias: MON$NEXT_ATTACHMENT + 04: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: MON$NEXT_STATEMENT alias: MON$NEXT_STATEMENT + 05: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 {SQL_SCHEMA_PREFIX}NONE + : name: RDB$GET_CONTEXT alias: RDB$GET_CONTEXT + 06: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 255 charset: 0 {SQL_SCHEMA_PREFIX}NONE + : name: RDB$GET_CONTEXT alias: RDB$GET_CONTEXT + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 7b43d6eb2e604e177e64dcf34e9ccf6ac35b02ad Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 13:53:55 +0300 Subject: [PATCH 0982/1064] Added/Updated tests\bugs\core_6316_test.py: Adjusted expected_output for FB 6.x: min page_size is 8192. Checked on 6.0.0.892 --- tests/bugs/core_6316_test.py | 41 ++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/bugs/core_6316_test.py b/tests/bugs/core_6316_test.py index 502d086e..9c0481f2 100644 --- a/tests/bugs/core_6316_test.py +++ b/tests/bugs/core_6316_test.py @@ -17,6 +17,11 @@ [13.03.2025] pzotov Changed expected out for 6.x after fixed https://github.com/FirebirdSQL/firebird/issues/8470. Question about 'page size NULL' and 'page size DEFAULT' not yet resolved: whether they allowed or no. + + [03.07.2025] pzotov + Adjusted expected_output for FB 6.x: min page_size is 8192. + ::: NB ::: Test diration time is about 75 seconds. + Checked on 6.0.0.892 """ import pytest @@ -402,41 +407,41 @@ def test_1(act: Action, capsys): create database ... page_size 8191 DB created. Actual page_size: 8192 create database ... page_size 4097 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 4097 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 4096 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 4096 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 4095 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 4095 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2049 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2049 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2048 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2048 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2047 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 2047 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1025 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1025 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1024 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1024 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1023 default character set win1251 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 1023 - DB created. Actual page_size: 4096 + DB created. Actual page_size: 8192 create database ... page_size 0 default character set win1251 DB created. Actual page_size: 8192 create database ... page_size 0 From f57c7af68026aa067a7a17d168382fdcc182bf34 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 14:57:46 +0300 Subject: [PATCH 0983/1064] Added/Updated tests\bugs\core_6343_test.py: Suppress name of stored procedure from output - it has no matter in this test. --- tests/bugs/core_6343_test.py | 40 +++++++++++++----------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/tests/bugs/core_6343_test.py b/tests/bugs/core_6343_test.py index 714d5fce..2cc9887d 100644 --- a/tests/bugs/core_6343_test.py +++ b/tests/bugs/core_6343_test.py @@ -7,6 +7,9 @@ DESCRIPTION: JIRA: CORE-6343 FBTEST: bugs.core_6343 +notes: + [03.07.2025] pzotov + Suppress name of stored procedure from output - it has no matter in this test. """ import pytest @@ -82,48 +85,33 @@ """ -act = isql_act('db', test_script, substitutions=[('line:.*', '')]) +act = isql_act('db', test_script, substitutions=[('line:.*', ''), ('(-)?At procedure .*', '')]) expected_stdout = """ - 1 - 2 - - 1 - 2 - - 1 - 2 - - 1 - 2 -""" - -expected_stderr = """ + 1 + 2 Statement failed, SQLSTATE = 22012 arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - -At procedure 'SP_TEST' - + 1 + 2 Statement failed, SQLSTATE = 22012 arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - -At procedure 'SP_TEST' - + 1 + 2 Statement failed, SQLSTATE = 22012 arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - -At procedure 'SP_TEST' - + 1 + 2 Statement failed, SQLSTATE = 22012 arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - -At procedure 'SP_TEST' """ @pytest.mark.version('>=3.0.6') def test_1(act: Action): act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr - and act.clean_stdout == act.clean_expected_stdout) + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 9b9853ec9b9915454b37aae32f2e0bf646ccb3ce Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:02:00 +0300 Subject: [PATCH 0984/1064] Added/Updated tests\bugs\core_6353_test.py: Separated expected output for FB major versions prior/since 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. --- tests/bugs/core_6353_test.py | 67 ++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_6353_test.py b/tests/bugs/core_6353_test.py index 22121d59..b8aff723 100644 --- a/tests/bugs/core_6353_test.py +++ b/tests/bugs/core_6353_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-6353 FBTEST: bugs.core_6353 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -193,7 +198,7 @@ act = isql_act('db', test_script, substitutions=[('line: [\\d]+, col: [\\d]+', ''), ('[ \t]+', ' ')]) -expected_stdout = """ +expected_stdout_5x = """ ID 1 ID2 170141183460469231731687303715884105726 ID -9223372036854775808 @@ -220,30 +225,70 @@ I_MAX 170141183460469231731687303715884105727 I_MIN -170141183460469231731687303715884105728 I_MAX 170141183460469231731687303715884105727 + Statement failed, SQLSTATE = 23000 + validation error for column "TEST2"."I_MIN", value "-2" + Statement failed, SQLSTATE = 23000 + validation error for column "TEST2"."I_MIN", value "2" V_MIN -170141183460469231731687303715884105728 V_MIN 170141183460469231731687303715884105727 P_MIN 170141183460469231731687303715884105727 P_MAX -170141183460469231731687303715884105728 + Statement failed, SQLSTATE = HY000 + exception 1 + -EX_ZERO_DIV_NOT_ALLOWED + -Can not delete -170141183460469231731687303715884105728 by zero + -At procedure 'SP_ZERO_DIV' P_MIN 1 P_MIN -1 """ -expected_stderr = """ +expected_stdout_6x = """ + ID 1 + ID2 170141183460469231731687303715884105726 + ID -9223372036854775808 + ID2 -1 + ID 9223372036854775807 + ID2 -1 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 + PLAN ("PUBLIC"."V_TEST0" "PUBLIC"."TEST0" ORDER "PUBLIC"."TEST0_I_MIN_DEC") + MAX -170141183460469231731687303715884105728 + PLAN ("PUBLIC"."V_TEST0" "PUBLIC"."TEST0" ORDER "PUBLIC"."TEST0_I_MIN_ASC") + MIN -170141183460469231731687303715884105728 + PLAN ("PUBLIC"."V_TEST0" "PUBLIC"."TEST0" ORDER "PUBLIC"."TEST0_I_MAX_DEC") + MAX 170141183460469231731687303715884105727 + PLAN ("PUBLIC"."V_TEST0" "PUBLIC"."TEST0" ORDER "PUBLIC"."TEST0_I_MAX_ASC") + MIN 170141183460469231731687303715884105727 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 + I_MIN -170141183460469231731687303715884105728 + I_MAX 170141183460469231731687303715884105727 Statement failed, SQLSTATE = 23000 - validation error for column "TEST2"."I_MIN", value "-2" + validation error for column "PUBLIC"."TEST2"."I_MIN", value "-2" Statement failed, SQLSTATE = 23000 - validation error for column "TEST2"."I_MIN", value "2" + validation error for column "PUBLIC"."TEST2"."I_MIN", value "2" + V_MIN -170141183460469231731687303715884105728 + V_MIN 170141183460469231731687303715884105727 + P_MIN 170141183460469231731687303715884105727 + P_MAX -170141183460469231731687303715884105728 Statement failed, SQLSTATE = HY000 exception 1 - -EX_ZERO_DIV_NOT_ALLOWED + -"PUBLIC"."EX_ZERO_DIV_NOT_ALLOWED" -Can not delete -170141183460469231731687303715884105728 by zero - -At procedure 'SP_ZERO_DIV' line: 8, col: 12 + -At procedure "PUBLIC"."SP_ZERO_DIV" + P_MIN 1 + P_MIN -1 """ + @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 54f155b3fba0ff123026d9e10fefb15badee4050 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:38:11 +0300 Subject: [PATCH 0985/1064] Added/Updated tests\bugs\core_6411_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x. Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214 --- tests/bugs/core_6411_test.py | 95 ++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/tests/bugs/core_6411_test.py b/tests/bugs/core_6411_test.py index 157d55f1..72d34dc3 100644 --- a/tests/bugs/core_6411_test.py +++ b/tests/bugs/core_6411_test.py @@ -5,50 +5,38 @@ ISSUE: 6649 TITLE: FB crashes on attempt to create table with number of fields greater than 5460 DESCRIPTION: - It was found that maximal number of fields with type = BIGINT that could fit in a table DDL is 8066. - If this limit is exeeded then FB raises "new record size of N bytes is too big" (where N >= 65536). - We use for-loop with two iterations, each of them does following: - 1. Create table with total number of fields = (one for 'ID primary key' plus 8064 for - 'user-data' fields with names 'F1', 'F2', ..., 'F'-1). All of them have type = BIGINT. - 2. DO RECONNECT // mandatory! otherwise crash can not be reproduced. - 3. Run UPDATE OR INSERT statement that is specified in the ticker(insert single record with ID=1). - 4. Run SELECT statement which calculates total sum on all 'user-data' fields. - When N = 8065 then these actions must complete successfully and result of final SELECT must be displayed. - When N = 8066 then we have to get exception: - Statement failed, SQLSTATE = 54000 - unsuccessful metadata update - -new record size of 65536 bytes is too big - - Confirmed bug on 4.0.0.2204: got crash when N=8065 (but still "new record size of 65536 bytes is too big" when N=8066). - Checked on 3.0.7.33368, 4.0.0.2214 - all OK. -NOTES: -[08.02.2022] pcisar - Fails on Windows 3.0.8 with diff: - step: 0, FLD_COUNT: 8064, result: FIELDS_TOTAL 32510016 - step: 1, FLD_COUNT: 8065, result: Statement failed, SQLSTATE = 54000 - step: 1, FLD_COUNT: 8065, result: unsuccessful metadata update - step: 1, FLD_COUNT: 8065, result: -new record size of 65536 bytes is too big - - step: 1, FLD_COUNT: 8065, result: -TABLE TDATA - + step: 1, FLD_COUNT: 8065, result: -TABLE TDATA - ? + - + step: 1, FLD_COUNT: 8065, result: Statement failed, SQLSTATE = 21S01 - + step: 1, FLD_COUNT: 8065, result: Dynamic SQL Error - + step: 1, FLD_COUNT: 8065, result: -SQL error code = -804 - + step: 1, FLD_COUNT: 8065, result: -Count of read-write columns does not equal count of values - -[24.03.2022] pzotov - On WINDOWS excessive lines in STDERR (after first error) appear because ISQL ignores 'SET BAIL' command or '-bail' switch - in case when it executing commands that come via PIPE mechanism. - Discussed with FB-team, letter with subj "[new-qa] ISQL "SET BAIL ON" problem on Windows when commands come from PIPE", 12-mar-2022 16:04. - It looks strange but such behaviour was considered as DESIRED feature and requested long ago (in 2011). - This means that it is very unlikely that it will be fixed and ISQL will behave like on POSIX (where no such effect occurs). - Because of this, it was decided to change test: we create temporary SQL file and provide this file as input script for launching ISQL, - see: - act.isql(..., input_file=isql_script, ...) - - + It was found that maximal number of fields with type = BIGINT that could fit in a table DDL is 8066. + If this limit is exeeded then FB raises "new record size of N bytes is too big" (where N >= 65536). + We use for-loop with two iterations, each of them does following: + 1. Create table with total number of fields = (one for 'ID primary key' plus 8064 for + 'user-data' fields with names 'F1', 'F2', ..., 'F'-1). All of them have type = BIGINT. + 2. DO RECONNECT // mandatory! otherwise crash can not be reproduced. + 3. Run UPDATE OR INSERT statement that is specified in the ticker(insert single record with ID=1). + 4. Run SELECT statement which calculates total sum on all 'user-data' fields. + When N = 8065 then these actions must complete successfully and result of final SELECT must be displayed. + When N = 8066 then we have to get exception: + Statement failed, SQLSTATE = 54000 + unsuccessful metadata update + -new record size of 65536 bytes is too big + + Confirmed bug on 4.0.0.2204: got crash when N=8065 (but still "new record size of 65536 bytes is too big" when N=8066). + Checked on 3.0.7.33368, 4.0.0.2214 - all OK. JIRA: CORE-6411 FBTEST: bugs.core_6411 +NOTES: + [24.03.2022] pzotov + On WINDOWS excessive lines in STDERR (after first error) appear because ISQL ignores 'SET BAIL' command or '-bail' switch + in case when it executing commands that come via PIPE mechanism. + Discussed with FB-team, letter with subj "[new-qa] ISQL "SET BAIL ON" problem on Windows when commands come from PIPE", 12-mar-2022 16:04. + It looks strange but such behaviour was considered as DESIRED feature and requested long ago (in 2011). + This means that it is very unlikely that it will be fixed and ISQL will behave like on POSIX (where no such effect occurs). + Because of this, it was decided to change test: we create temporary SQL file and provide this file as input script for launching ISQL, + see: + act.isql(..., input_file=isql_script, ...) + [03.07.2025] pzotov + ::: NB ::: test duration time is ~6 minutes. + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.884; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -61,18 +49,8 @@ act = python_act('db', substitutions=[('.*(-)?After line \\d+.*', ''), ('[ \t]+', ' ')]) -expected_stdout = """ - step: 0, FLD_COUNT: 8064, result: FIELDS_TOTAL 32510016 - step: 1, FLD_COUNT: 8065, result: Statement failed, SQLSTATE = 54000 - step: 1, FLD_COUNT: 8065, result: unsuccessful metadata update - step: 1, FLD_COUNT: 8065, result: -new record size of 65536 bytes is too big - step: 1, FLD_COUNT: 8065, result: -TABLE TDATA -""" - - isql_script = temp_file('test-script-6411.sql') - @pytest.mark.version('>=3.0.7') def test_1(act: Action, isql_script: Path, capsys): for step in range(0,2): @@ -95,7 +73,7 @@ def test_1(act: Action, isql_script: Path, capsys): set list on ; {sel_expr} ; quit ; - """ + """ isql_script.write_text(sql_expr) act.reset() @@ -106,6 +84,17 @@ def test_1(act: Action, isql_script: Path, capsys): print(f'step: {step}, FLD_COUNT: {FLD_COUNT}, result: {line}') act.reset() + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_NAME = 'TDATA' if act.is_version('<6') else '"TDATA"' + expected_stdout = f""" + step: 0, FLD_COUNT: 8064, result: FIELDS_TOTAL 32510016 + step: 1, FLD_COUNT: 8065, result: Statement failed, SQLSTATE = 54000 + step: 1, FLD_COUNT: 8065, result: unsuccessful metadata update + step: 1, FLD_COUNT: 8065, result: -new record size of 65536 bytes is too big + step: 1, FLD_COUNT: 8065, result: -TABLE {SQL_SCHEMA_PREFIX}{TABLE_NAME} + """ + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out From 6b68a6989e875183201584c5974034fa867d9ee2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:40:52 +0300 Subject: [PATCH 0986/1064] Added/Updated tests\bugs\core_6440_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_6440_test.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/bugs/core_6440_test.py b/tests/bugs/core_6440_test.py index 9833c0b2..2662b7d5 100644 --- a/tests/bugs/core_6440_test.py +++ b/tests/bugs/core_6440_test.py @@ -4,11 +4,15 @@ ID: issue-6674 ISSUE: 6674 TITLE: Expression indexes containing COALESCE inside cannot be matched by the optimizer - after migration from v2.5 to v3.0 DESCRIPTION: Test uses .fbk that was created on FB 2.5.9, file: core6440-ods11.fbk JIRA: CORE-6440 FBTEST: bugs.core_6440 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -47,20 +51,24 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST INDEX (PK_TEST)) - PLAN (TEST INDEX (TEST_IDX4)) - PLAN (TEST INDEX (TEST_IDX3)) - PLAN (TEST INDEX (TEST_IDX2)) - PLAN (TEST INDEX (TEST_IDX1)) """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."PK_TEST")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX4")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX3")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX2")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX1")) +""" + @pytest.mark.version('>=3.0.8') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1938d2ae9ff6c089903aa67992d83e702caacfb5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:42:49 +0300 Subject: [PATCH 0987/1064] Added/Updated tests\bugs\core_6444_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_6444_test.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_6444_test.py b/tests/bugs/core_6444_test.py index 87757aac..d06c4847 100644 --- a/tests/bugs/core_6444_test.py +++ b/tests/bugs/core_6444_test.py @@ -15,6 +15,10 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import os import pytest @@ -31,18 +35,20 @@ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = """ + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + act.expected_stdout = f""" 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 : name: RDB$CONFIG_ID alias: RDB$CONFIG_ID - 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 63 charset: 2 ASCII + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 63 charset: 2 {SQL_SCHEMA_PREFIX}ASCII : name: RDB$CONFIG_NAME alias: RDB$CONFIG_NAME - 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 + 03: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 : name: RDB$CONFIG_VALUE alias: RDB$CONFIG_VALUE - 04: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 + 04: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 : name: RDB$CONFIG_DEFAULT alias: RDB$CONFIG_DEFAULT 05: sqltype: 32764 BOOLEAN scale: 0 subtype: 0 len: 1 : name: RDB$CONFIG_IS_SET alias: RDB$CONFIG_IS_SET - 06: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 + 06: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 : name: RDB$CONFIG_SOURCE alias: RDB$CONFIG_SOURCE """ act.execute(combine_output = True) From 107632d227ea546944d86348932c737243555ee6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:46:20 +0300 Subject: [PATCH 0988/1064] Added/Updated tests\bugs\core_6487_test.py: Suppressed name of cursor - it has no matter in this test. --- tests/bugs/core_6487_test.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/bugs/core_6487_test.py b/tests/bugs/core_6487_test.py index 38a51bb8..a5aa77f6 100644 --- a/tests/bugs/core_6487_test.py +++ b/tests/bugs/core_6487_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-6487 FBTEST: bugs.core_6487 +NOTES: + [03.07.2025] pzotov + Suppressed name of cursor - it has no matter in this test. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -61,20 +65,20 @@ set term ;^ """ -act = isql_act('db', test_script, substitutions=[('-At block line:.*', '-At block line')]) +act = isql_act('db', test_script, substitutions=[('-At block line:.*', '-At block line'), ('Cursor \\S+ is not positioned', 'Cursor is not positioned')]) -expected_stderr = """ +expected_stdout = """ Statement failed, SQLSTATE = HY109 - Cursor C is not positioned in a valid record - -At block line: 14, col: 5 + Cursor is not positioned in a valid record + -At block line Statement failed, SQLSTATE = HY109 - Cursor C is not positioned in a valid record - -At block line: 14, col: 5 + Cursor is not positioned in a valid record + -At block line """ @pytest.mark.version('>=3.0.8') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 1064e9ce5e28a568c28ae2eb5eeecc925e4ea4e0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 15:52:29 +0300 Subject: [PATCH 0989/1064] Added/Updated tests\bugs\core_6489_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_6489_test.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/tests/bugs/core_6489_test.py b/tests/bugs/core_6489_test.py index 8648fc2f..358bd24d 100644 --- a/tests/bugs/core_6489_test.py +++ b/tests/bugs/core_6489_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-6489 FBTEST: bugs.core_6489 + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.889; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -37,26 +41,32 @@ commit; """ -act = isql_act('db', test_script, - substitutions=[('ROLE_DESCR_BLOB_ID .*', ''), ('[\t ]+', ' '), - ('(-)?Effective user is.*', '')]) +substitutions = [ + ('[\t ]+', ' '), + ('ROLE_DESCR_BLOB_ID .*', ''), + ('(-)?Effective user is.*', ''), +] -expected_stdout = """ - Comment by tmp$c6489_senior -""" +act = isql_act('db', test_script, substitutions = substitutions) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update -COMMENT ON RDB$ADMIN failed -no permission for ALTER access to ROLE RDB$ADMIN - -Effective user is TMP$C6489_JUNIOR + Comment by tmp$c6489_senior +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -COMMENT ON "RDB$ADMIN" failed + -no permission for ALTER access to ROLE "RDB$ADMIN" + Comment by tmp$c6489_senior """ @pytest.mark.version('>=3.0.8') def test_1(act: Action, user_sr, user_jr): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 5b4979fa9495d75ed32ad1cc90bedb3ba5f28fdb Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 18:26:02 +0300 Subject: [PATCH 0990/1064] Removed excessive double quotes. Fixed by 6b6e57b2, 'Fix error messages.', 03.07.2025 --- tests/bugs/core_2916_test.py | 2 +- tests/bugs/core_4075_test.py | 4 ++-- tests/bugs/core_6015_test.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_2916_test.py b/tests/bugs/core_2916_test.py index 710cdc48..25b881ec 100644 --- a/tests/bugs/core_2916_test.py +++ b/tests/bugs/core_2916_test.py @@ -46,7 +46,7 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 22018 - Expression evaluation error for index ""***unknown***"" on table ""PUBLIC"."TAB"" + Expression evaluation error for index "***unknown***" on table "PUBLIC"."TAB" conversion error from string "2021-09-27" """ diff --git a/tests/bugs/core_4075_test.py b/tests/bugs/core_4075_test.py index 6ade6ec1..51aa0beb 100644 --- a/tests/bugs/core_4075_test.py +++ b/tests/bugs/core_4075_test.py @@ -70,12 +70,12 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 - Expression evaluation error for index ""PUBLIC"."IDX_TEST_BIT"" on table ""PUBLIC"."TEST"" + Expression evaluation error for index "PUBLIC"."IDX_TEST_BIT" on table "PUBLIC"."TEST" expression evaluation not supported Argument for BIN_SHL must be zero or positive Statement failed, SQLSTATE = 22018 - Expression evaluation error for index ""PUBLIC"."T_INDEX"" on table ""PUBLIC"."T_TABLE"" + Expression evaluation error for index "PUBLIC"."T_INDEX" on table "PUBLIC"."T_TABLE" conversion error from string "2014.02.33" """ diff --git a/tests/bugs/core_6015_test.py b/tests/bugs/core_6015_test.py index 36e6ea18..c6b906dc 100644 --- a/tests/bugs/core_6015_test.py +++ b/tests/bugs/core_6015_test.py @@ -132,10 +132,10 @@ expected_stdout_6x = """ Statement failed, SQLSTATE = 42000 - Expression evaluation error for index ""PUBLIC"."TEST_STATIC_PSQL_EVAL"" on table ""PUBLIC"."TEST_STATIC_PSQL"" + Expression evaluation error for index "PUBLIC"."TEST_STATIC_PSQL_EVAL" on table "PUBLIC"."TEST_STATIC_PSQL" -Attempt to evaluate index expression recursively Statement failed, SQLSTATE = 42000 - Expression evaluation error for index ""PUBLIC"."TEST_DYNAMIC_SQL_EVAL"" on table ""PUBLIC"."TEST_DYNAMIC_SQL"" + Expression evaluation error for index "PUBLIC"."TEST_DYNAMIC_SQL_EVAL" on table "PUBLIC"."TEST_DYNAMIC_SQL" -Attempt to evaluate index expression recursively """ From 8b85de8c3b32bdb4ae4ad11c16e9b5d96e255b10 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 18:53:34 +0300 Subject: [PATCH 0991/1064] Updated tests\bugs\core_3735_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_3735_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_3735_test.py b/tests/bugs/core_3735_test.py index 142e2dba..dcd97243 100644 --- a/tests/bugs/core_3735_test.py +++ b/tests/bugs/core_3735_test.py @@ -210,7 +210,7 @@ def test_1(act: Action, tmp_user: User): expected_stdout_6x = f""" USER {tmp_user.name.upper()} - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC Statement failed, SQLSTATE = 28000 no permission for INSERT access to TABLE "SYSTEM"."RDB$CHARACTER_SETS" -Effective user is {tmp_user.name.upper()} From aa5919a9333ce5d2f3ee1aeacdf4fde6b92f84b4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 18:54:40 +0300 Subject: [PATCH 0992/1064] Updated tests\bugs\core_4122_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4122_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_4122_test.py b/tests/bugs/core_4122_test.py index b7a82a10..f55eebfe 100644 --- a/tests/bugs/core_4122_test.py +++ b/tests/bugs/core_4122_test.py @@ -195,7 +195,7 @@ COMMIT WORK; SET AUTODDL ON; /* Grant permissions for this database */ - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC; + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC; """ From ec24bb384000ddabeb953c4c15cce4f5b55fba24 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 18:55:24 +0300 Subject: [PATCH 0993/1064] Updated tests\bugs\core_4137_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4137_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_4137_test.py b/tests/bugs/core_4137_test.py index 4e0a497a..bba3d0e9 100644 --- a/tests/bugs/core_4137_test.py +++ b/tests/bugs/core_4137_test.py @@ -101,7 +101,7 @@ COMMIT WORK; SET AUTODDL ON; /* Grant permissions for this database */ - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC; + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC; """ @pytest.mark.version('>=3.0') From 1b39e8cfc38a877313020828bd83b283fc2902a0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 18:56:07 +0300 Subject: [PATCH 0994/1064] Updated tests\bugs\core_4149_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4149_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/bugs/core_4149_test.py b/tests/bugs/core_4149_test.py index 7f918af8..c03e79d7 100644 --- a/tests/bugs/core_4149_test.py +++ b/tests/bugs/core_4149_test.py @@ -48,13 +48,13 @@ expected_stdout_6x = """ /* Grant permissions for this database */ - GRANT SELECT ON PUBLIC.TEST TO USER PUBLIC - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + GRANT SELECT ON PUBLIC.TEST TO PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC /* Grant permissions for this database */ - GRANT SELECT ON PUBLIC.TEST TO USER PUBLIC - GRANT USAGE ON SEQUENCE PUBLIC.G_TEST TO USER PUBLIC - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + GRANT SELECT ON PUBLIC.TEST TO PUBLIC + GRANT USAGE ON SEQUENCE PUBLIC.G_TEST TO PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC """ @pytest.mark.version('>=3.0') From e74eb4fb2bc5b4347c566052ed4d917d1faa8210 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 20:08:06 +0300 Subject: [PATCH 0995/1064] Added/Updated tests\bugs\core_4802_test.py: Reimplemented: removed usage of hard-coded values for user and role name. SQL schema and double quotes must be taken in acount when specifying data in expected output. Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/core_4802_test.py | 213 +++++++++++++++++------------------ 1 file changed, 103 insertions(+), 110 deletions(-) diff --git a/tests/bugs/core_4802_test.py b/tests/bugs/core_4802_test.py index d615b730..3002474c 100644 --- a/tests/bugs/core_4802_test.py +++ b/tests/bugs/core_4802_test.py @@ -7,6 +7,11 @@ DESCRIPTION: JIRA: CORE-4802 FBTEST: bugs.core_4802 +NOTES: + [03.07.2025] pzotov + Reimplemented: removed usage of hard-coded values for user and role name. + SQL schema and double quotes must be taken in acount when specifying data in expected output. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -14,117 +19,105 @@ db = db_factory() -user_a = user_factory('db', name='BIG_BROTHER', password='123') -user_b = user_factory('db', name='SENIOR_MNGR', password='456') -user_c = user_factory('db', name='JUNIOR_MNGR', password='789') -role_a = role_factory('db', name='FLD_FOR_SENIORS_UPDATER') -role_b = role_factory('db', name='FLD_FOR_JUNIORS_UPDATER') +u_big_bro = user_factory('db', name='BIG_BROTHER', password='123') +u_senior = user_factory('db', name='SENIOR_MNGR', password='456') +u_junior = user_factory('db', name='JUNIOR_MNGR', password='789') +r_senior = role_factory('db', name='FLD_FOR_SENIORS_UPDATER') +r_junior = role_factory('db', name='FLD_FOR_JUNIORS_UPDATER') -test_script = """ - set wng off; - - recreate table test(fld_for_seniors varchar(70), fld_for_juniors varchar(70)); - commit; - - grant select on test to PUBLIC; - - grant update(fld_for_seniors) on test to BIG_BROTHER; - commit; - - grant update(fld_for_seniors) on test to FLD_FOR_SENIORS_UPDATER; - grant update(fld_for_juniors) on test to FLD_FOR_JUNIORS_UPDATER; - - grant FLD_FOR_SENIORS_UPDATER to SENIOR_MNGR; - grant FLD_FOR_JUNIORS_UPDATER to JUNIOR_MNGR; - commit; - - show grants; - - insert into test values( 'created by '||upper(current_user), 'created by '||lower(current_user) ); - commit; - set list on; - - --set echo on; - - connect '$(DSN)' user 'BIG_BROTHER' password '123'; - select current_user, current_role from rdb$database; - update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); - select * from test; - - update test set fld_for_juniors = 'updated by '||lower(current_user)||', role: '||lower(current_role); - select * from test; - commit; - --------------------------------------------------------------- - - connect '$(DSN)' user 'SENIOR_MNGR' password '456' role 'FLD_FOR_SENIORS_UPDATER'; - select current_user, current_role from rdb$database; - update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); - select * from test; - - update test set fld_for_juniors ='updated by '||lower(current_user)||', role: '||lower(current_role); - select * from test; - commit; - --------------------------------------------------------------- - - connect '$(DSN)' user 'JUNIOR_MNGR' password '789' role 'FLD_FOR_JUNIORS_UPDATER'; - select current_user, current_role from rdb$database; - update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); - select * from test; - - update test set fld_for_juniors ='updated by '||lower(current_user)||', role: '||lower(current_role); - select * from test; - commit; -""" - -act = isql_act('db', test_script, substitutions=[('GRANT.*TMP.*', ''), ('-Effective user is.*', '')]) - -expected_stdout = """ - /* Grant permissions for this database */ - GRANT UPDATE (FLD_FOR_SENIORS) ON TEST TO USER BIG_BROTHER - GRANT UPDATE (FLD_FOR_JUNIORS) ON TEST TO ROLE FLD_FOR_JUNIORS_UPDATER - GRANT UPDATE (FLD_FOR_SENIORS) ON TEST TO ROLE FLD_FOR_SENIORS_UPDATER - GRANT SELECT ON TEST TO PUBLIC - GRANT FLD_FOR_JUNIORS_UPDATER TO JUNIOR_MNGR - GRANT FLD_FOR_SENIORS_UPDATER TO SENIOR_MNGR - - USER BIG_BROTHER - ROLE NONE - FLD_FOR_SENIORS updated by BIG_BROTHER, role: NONE - FLD_FOR_JUNIORS created by sysdba - FLD_FOR_SENIORS updated by BIG_BROTHER, role: NONE - FLD_FOR_JUNIORS created by sysdba - - USER SENIOR_MNGR - ROLE FLD_FOR_SENIORS_UPDATER - FLD_FOR_SENIORS updated by SENIOR_MNGR, role: FLD_FOR_SENIORS_UPDATER - FLD_FOR_JUNIORS created by sysdba - FLD_FOR_SENIORS updated by SENIOR_MNGR, role: FLD_FOR_SENIORS_UPDATER - FLD_FOR_JUNIORS created by sysdba - - USER JUNIOR_MNGR - ROLE FLD_FOR_JUNIORS_UPDATER - FLD_FOR_SENIORS updated by SENIOR_MNGR, role: FLD_FOR_SENIORS_UPDATER - FLD_FOR_JUNIORS created by sysdba - FLD_FOR_SENIORS updated by SENIOR_MNGR, role: FLD_FOR_SENIORS_UPDATER - FLD_FOR_JUNIORS updated by junior_mngr, role: fld_for_juniors_updater -""" - -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to COLUMN TEST.FLD_FOR_JUNIORS - - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to COLUMN TEST.FLD_FOR_JUNIORS - - Statement failed, SQLSTATE = 28000 - no permission for UPDATE access to COLUMN TEST.FLD_FOR_SENIORS -""" +substitutions = [ ('[ \t]+', ' '), ('GRANT.*TMP.*', ''), ('-Effective user is.*', '') ] +act = isql_act('db', substitutions = substitutions) @pytest.mark.version('>=3.0') -def test_1(act: Action, user_a: User, user_b: User, user_c: User, role_a: Role, role_b: Role): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) +def test_1(act: Action, u_big_bro: User, u_senior: User, u_junior: User, r_senior: Role, r_junior: Role): + + test_script = f""" + set wng off; + + recreate table test(fld_for_seniors varchar(70), fld_for_juniors varchar(70)); + commit; + + grant select on test to PUBLIC; + + grant update(fld_for_seniors) on test to {u_big_bro.name}; + commit; + + grant update(fld_for_seniors) on test to {r_senior.name}; + grant update(fld_for_juniors) on test to {r_junior.name}; + + grant {r_senior.name} to {u_senior.name}; + grant {r_junior.name} to {u_junior.name}; + commit; + + insert into test values( 'created by ' || upper(current_user), 'created by ' || lower(current_user) ); + commit; + set list on; + + connect '{act.db.dsn}' user '{u_big_bro.name}' password '{u_big_bro.password}'; + select current_user, current_role from rdb$database; + update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); + select * from test; + + update test set fld_for_juniors = 'updated by '||lower(current_user)||', role: '||lower(current_role); + select * from test; + commit; + --------------------------------------------------------------- + + connect '{act.db.dsn}' user '{u_senior.name}' password '{u_senior.password}' role '{r_senior.name}'; + select current_user, current_role from rdb$database; + update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); + select * from test; + + update test set fld_for_juniors ='updated by '||lower(current_user)||', role: '||lower(current_role); + select * from test; + commit; + --------------------------------------------------------------- + + connect '{act.db.dsn}' user '{u_junior.name}' password '{u_junior.password}' role '{r_junior.name}'; + select current_user, current_role from rdb$database; + update test set fld_for_seniors = 'updated by '||upper(current_user)||', role: '||upper(current_role); + select * from test; + + update test set fld_for_juniors ='updated by '||lower(current_user)||', role: '||lower(current_role); + select * from test; + commit; + """ + + FLD_JUNIORS_NAME = 'TEST.FLD_FOR_JUNIORS' if act.is_version('<6') else '"PUBLIC"."TEST"."FLD_FOR_JUNIORS"' + FLD_SENIORS_NAME = 'TEST.FLD_FOR_SENIORS' if act.is_version('<6') else '"PUBLIC"."TEST"."FLD_FOR_SENIORS"' + expected_stdout = f""" + USER {u_big_bro.name.upper()} + ROLE NONE + FLD_FOR_SENIORS updated by {u_big_bro.name.upper()}, role: NONE + FLD_FOR_JUNIORS created by {act.db.user.lower()} + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to COLUMN {FLD_JUNIORS_NAME} + + FLD_FOR_SENIORS updated by {u_big_bro.name.upper()}, role: NONE + FLD_FOR_JUNIORS created by {act.db.user.lower()} + USER {u_senior.name.upper()} + ROLE {r_senior.name.upper()} + FLD_FOR_SENIORS updated by {u_senior.name.upper()}, role: {r_senior.name.upper()} + FLD_FOR_JUNIORS created by {act.db.user.lower()} + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to COLUMN {FLD_JUNIORS_NAME} + + FLD_FOR_SENIORS updated by {u_senior.name.upper()}, role: {r_senior.name.upper()} + FLD_FOR_JUNIORS created by {act.db.user.lower()} + USER {u_junior.name.upper()} + ROLE {r_junior.name.upper()} + + Statement failed, SQLSTATE = 28000 + no permission for UPDATE access to COLUMN {FLD_SENIORS_NAME} + + FLD_FOR_SENIORS updated by {u_senior.name.upper()}, role: {r_senior.name.upper()} + FLD_FOR_JUNIORS created by {act.db.user.lower()} + FLD_FOR_SENIORS updated by {u_senior.name.upper()}, role: {r_senior.name.upper()} + FLD_FOR_JUNIORS updated by junior_mngr, role: fld_for_juniors_updater + """ + act.expected_stdout = expected_stdout + act.isql(switches = ['-q'], input = test_script, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 116aa8f9067918ac2a1d5ddfc30c5783899979fc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 20:10:05 +0300 Subject: [PATCH 0996/1064] Updated tests\bugs\core_4836_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4836_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4836_test.py b/tests/bugs/core_4836_test.py index 1772d35b..5f964d9d 100644 --- a/tests/bugs/core_4836_test.py +++ b/tests/bugs/core_4836_test.py @@ -66,9 +66,9 @@ def test_1(act: Action, tmp_user: User, tmp_role: Role): """ expected_stdout_6x = f""" - GRANT UPDATE (TEXT) ON PUBLIC.TEST TO {tmp_user.name.upper()} WITH GRANT OPTION + GRANT UPDATE (TEXT) ON PUBLIC.TEST TO USER {tmp_user.name.upper()} WITH GRANT OPTION GRANT UPDATE (TEXT) ON PUBLIC.TEST TO ROLE {tmp_role.name.upper()} GRANTED BY {tmp_user.name.upper()} - GRANT UPDATE (TEXT) ON PUBLIC.TEST TO {tmp_user.name.upper()} WITH GRANT OPTION + GRANT UPDATE (TEXT) ON PUBLIC.TEST TO USER {tmp_user.name.upper()} WITH GRANT OPTION """ act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 2841a8518622227b247d30a0f3459c8defe026d8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 20:14:49 +0300 Subject: [PATCH 0997/1064] Updated tests\bugs\core_4839_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_4839_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bugs/core_4839_test.py b/tests/bugs/core_4839_test.py index db066dc9..d37631f3 100644 --- a/tests/bugs/core_4839_test.py +++ b/tests/bugs/core_4839_test.py @@ -50,8 +50,8 @@ def test_1(act: Action, tmp_user: User): """ expected_stdout_6x = f""" - GRANT USAGE ON SEQUENCE PUBLIC.GEN_BAR TO {tmp_user.name.upper()} - GRANT USAGE ON EXCEPTION PUBLIC.EXC_FOO TO {tmp_user.name.upper()} + GRANT USAGE ON SEQUENCE PUBLIC.GEN_BAR TO USER {tmp_user.name.upper()} + GRANT USAGE ON EXCEPTION PUBLIC.EXC_FOO TO USER {tmp_user.name.upper()} """ act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x From 9878b03e49bf9e51a479aee581cf979f1b88a702 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 20:18:45 +0300 Subject: [PATCH 0998/1064] Added/Updated tests\bugs\core_5606_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_5606_test.py | 62 +++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/tests/bugs/core_5606_test.py b/tests/bugs/core_5606_test.py index 26bed86e..d1ba319c 100644 --- a/tests/bugs/core_5606_test.py +++ b/tests/bugs/core_5606_test.py @@ -5,16 +5,20 @@ ISSUE: 5872 TITLE: Add expression index name to exception message if computation failed DESCRIPTION: -NOTES: -[24.08.2020] - changed sequence of actions: one statement must violate requirements of only ONE index. - Before this statement: - insert into test(id, x, y, s) values( 4, 3, -7, 'qwerty' ); - -- did violate TWO indices: test_eval3 and test_eval5. - The order of which of them will raise first is undefined, so this test could fail because of appearance - "wrong" index name in its STDERR. Detected on 4.0.0.2173. Discussed with hvlad, letter 23.08.2020 16:58. JIRA: CORE-5606 FBTEST: bugs.core_5606 +NOTES: + [24.08.2020] + Changed sequence of actions: one statement must violate requirements of only ONE index. + Before this statement: + insert into test(id, x, y, s) values( 4, 3, -7, 'qwerty' ); + -- did violate TWO indices: test_eval3 and test_eval5. + The order of which of them will raise first is undefined, so this test could fail because of appearance + "wrong" index name in its STDERR. Detected on 4.0.0.2173. Discussed with hvlad, letter 23.08.2020 16:58. + [30.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.881; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -61,39 +65,53 @@ act = isql_act('db', test_script) -expected_stdout = """ - Records affected: 0 -""" - -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 22012 Expression evaluation error for index "TEST_EVAL1" on table "TEST" -arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - Statement failed, SQLSTATE = 42000 Expression evaluation error for index "TEST_EVAL2" on table "TEST" -expression evaluation not supported -Argument for LOG10 must be positive - Statement failed, SQLSTATE = HY000 Expression evaluation error for index "TEST_EVAL3" on table "TEST" -Context variable 'FOO_&_BAR' is not found in namespace 'SYSTEM' Statement failed, SQLSTATE = 22012 - Expression evaluation error for index "TEST_EVAL4" on table "TEST" -arithmetic exception, numeric overflow, or string truncation -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. - Statement failed, SQLSTATE = 22011 Expression evaluation error for index "TEST_EVAL5" on table "TEST" -Invalid length parameter -3 to SUBSTRING. Negative integers are not allowed. + Records affected: 0 +""" + +expected_stdout_6x = """ + Statement failed, SQLSTATE = 22012 + Expression evaluation error for index "PUBLIC"."TEST_EVAL1" on table "PUBLIC"."TEST" + -arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + Statement failed, SQLSTATE = 42000 + Expression evaluation error for index "PUBLIC"."TEST_EVAL2" on table "PUBLIC"."TEST" + -expression evaluation not supported + -Argument for LOG10 must be positive + Statement failed, SQLSTATE = HY000 + Expression evaluation error for index "PUBLIC"."TEST_EVAL3" on table "PUBLIC"."TEST" + -Context variable 'FOO_&_BAR' is not found in namespace 'SYSTEM' + Statement failed, SQLSTATE = 22012 + Expression evaluation error for index "PUBLIC"."TEST_EVAL4" on table "PUBLIC"."TEST" + -arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + Statement failed, SQLSTATE = 22011 + Expression evaluation error for index "PUBLIC"."TEST_EVAL5" on table "PUBLIC"."TEST" + -Invalid length parameter -3 to SUBSTRING. Negative integers are not allowed. + Records affected: 0 """ @pytest.mark.version('>=4.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 7b104057001b547ba1ad1545a0d43a397c5c7c75 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 21:00:12 +0300 Subject: [PATCH 0999/1064] Added/Updated tests\bugs\core_5659_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_5659_test.py | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/bugs/core_5659_test.py b/tests/bugs/core_5659_test.py index 96fd4122..f0735931 100644 --- a/tests/bugs/core_5659_test.py +++ b/tests/bugs/core_5659_test.py @@ -5,10 +5,15 @@ ISSUE: 5925 TITLE: Bad PLAN generated for query on Firebird v3.0 DESCRIPTION: - Test is based on data from original database that was provided in the ticket by its author. - Lot of data from tables were removed in order to reduce DB size. + Test is based on data from original database that was provided in the ticket by its author. + Lot of data from tables were removed in order to reduce DB size. JIRA: CORE-5659 FBTEST: bugs.core_5659 +NOTES: + [03.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -18,12 +23,16 @@ db = db_factory() -act_1 = python_act('db') +act = python_act('db') -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (B INDEX (COM_PEDIDO_IDX1), A INDEX (FK_COM_PEDIDO_ITEM_PEDIDO), C INDEX (PK_EST_PRODUTO)) """ +expected_stdout_6x = """ + PLAN JOIN ("B" INDEX ("PUBLIC"."COM_PEDIDO_IDX1"), "A" INDEX ("PUBLIC"."FK_COM_PEDIDO_ITEM_PEDIDO"), "C" INDEX ("PUBLIC"."PK_EST_PRODUTO")) +""" + test_script = """ set planonly; select @@ -42,14 +51,14 @@ fdb_file = temp_file('bad_plan_5659.fdb') @pytest.mark.version('>=3.0') -def test_1(act_1: Action, fbk_file: Path, fdb_file: Path): - zipped_fbk_file = zipfile.Path(act_1.files_dir / 'core_5659.zip', at='core_5659.fbk') +def test_1(act: Action, fbk_file: Path, fdb_file: Path): + zipped_fbk_file = zipfile.Path(act.files_dir / 'core_5659.zip', at='core_5659.fbk') fbk_file.write_bytes(zipped_fbk_file.read_bytes()) # - with act_1.connect_server() as srv: + with act.connect_server() as srv: srv.database.restore(backup=fbk_file, database=fdb_file) srv.wait() - # - act_1.expected_stdout = expected_stdout - act_1.isql(switches=['-q', act_1.get_dsn(fdb_file)], input=test_script, connect_db=False) - assert act_1.clean_stdout == act_1.clean_expected_stdout + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q', act.get_dsn(fdb_file)], input=test_script, connect_db=False, combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 0cab3af13e04638aeaf9deee12564f022e3446bf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 21:29:06 +0300 Subject: [PATCH 1000/1064] Added/Updated tests\bugs\core_5746_test.py: SEE NOTES. Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/core_5746_test.py | 154 ++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 65 deletions(-) diff --git a/tests/bugs/core_5746_test.py b/tests/bugs/core_5746_test.py index 3507684c..7f0b3dca 100644 --- a/tests/bugs/core_5746_test.py +++ b/tests/bugs/core_5746_test.py @@ -16,95 +16,119 @@ Restictions about create/alter/drop indexes on system tables that are checked by test for CORE-4731 should be removed. JIRA: CORE-5746 FBTEST: bugs.core_5746 +NOTES: + [03.07.2025] pzotov + 1. ::: NB ::: + For ALTER, DROP, and others statements, Firebird searches for the specified object across all schemas in the search path. + The reference is bound to the first matching object found. + Because of that, on 6.x following syntax should be used for GRANT ALTER ANY TABLE: + grant alter any table on schema system to tmp$c5746; + Explained by Adriano, letter 03.07.2025 + 2. Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ - +import locale import pytest from firebird.qa import * db = db_factory() -test_script = """ - set list on; - set plan on; - create descending index systable_comm_idx on rdb$relations(rdb$format); - create descending index systable_calc_idx on rdb$relations computed by ( 1 + rdb$format ); - set statistics index systable_comm_idx; - set statistics index systable_calc_idx; +tmp_user = user_factory('db', name = 'tmp$c5746', password = '123') +act = isql_act('db', substitutions=[('-Effective user is.*', '')]) + +expected_stdout_5x = """ + PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) + SIGN_COUNT 1 + PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) + SIGN_COUNT 1 + + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE INDEX SYSTABLE_COMM_IDX failed + -no permission for ALTER access to TABLE RDB$RELATIONS - select sign(count(*)) as sign_count from rdb$relations where rdb$format < 65537; - select sign(count(*)) as sign_count from rdb$relations where 1 + rdb$format < 65537; + PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) + SIGN_COUNT 1 + PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) + SIGN_COUNT 1 +""" - alter index systable_calc_idx inactive; - alter index systable_calc_idx active; +expected_stdout_6x = """ + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."SYSTABLE_COMM_IDX")) + SIGN_COUNT 1 + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."SYSTABLE_CALC_IDX")) + SIGN_COUNT 1 - drop index systable_comm_idx; - drop index systable_calc_idx; - commit; + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -CREATE INDEX "SYSTEM"."SYSTABLE_COMM_IDX" failed + -no permission for ALTER access to TABLE "SYSTEM"."RDB$RELATIONS" - create or alter user tmp$c5746 password '123'; - commit; + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."SYSTABLE_COMM_IDX")) + SIGN_COUNT 1 + PLAN ("SYSTEM"."RDB$RELATIONS" INDEX ("SYSTEM"."SYSTABLE_CALC_IDX")) + SIGN_COUNT 1 +""" - connect '$(DSN)' user tmp$c5746 password '123'; - -- this should FAIL: - create descending index systable_comm_idx on rdb$relations(rdb$format); - commit; +@pytest.mark.version('>=3.0.4') +def test_1(act: Action, tmp_user: User): + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'ON SCHEMA SYSTEM' + GRANT_ALTER_ANY_TABLE_EXPR = f'grant alter any table {SQL_SCHEMA_PREFIX} to {tmp_user.name};' + # grant alter any table to tmp$c5746; + # grant alter any table on schema system to tmp$c5746; - connect '$(DSN)' user 'SYSDBA' password 'masterkey'; - grant alter any table to tmp$c5746; - commit; + test_script = f""" + set list on; + set plan on; + create descending index systable_comm_idx on rdb$relations(rdb$format); + create descending index systable_calc_idx on rdb$relations computed by ( 1 + rdb$format ); + set statistics index systable_comm_idx; + set statistics index systable_calc_idx; + select sign(count(*)) as sign_count from rdb$relations where rdb$format < 65537; + select sign(count(*)) as sign_count from rdb$relations where 1 + rdb$format < 65537; - connect '$(DSN)' user tmp$c5746 password '123'; - -- All following statements should PASS: - create descending index systable_comm_idx on rdb$relations(rdb$format); - create descending index systable_calc_idx on rdb$relations computed by ( 1 + rdb$format ); - set statistics index systable_comm_idx; - set statistics index systable_calc_idx; + alter index systable_calc_idx inactive; + alter index systable_calc_idx active; - select sign(count(*)) as sign_count from rdb$relations where rdb$format < 65537; - select sign(count(*)) as sign_count from rdb$relations where 1 + rdb$format < 65537; + drop index systable_comm_idx; + drop index systable_calc_idx; + commit; - alter index systable_calc_idx inactive; - alter index systable_calc_idx active; + connect '{act.db.dsn}' user {tmp_user.name} password '{tmp_user.password}'; + -- this should FAIL: + create descending index systable_comm_idx on rdb$relations(rdb$format); + commit; - drop index systable_comm_idx; - drop index systable_calc_idx; - commit; + connect '{act.db.dsn}' user '{act.db.user}' password '{act.db.password}'; - connect '$(DSN)' user 'SYSDBA' password 'masterkey'; - drop user tmp$c5746; - commit; + {GRANT_ALTER_ANY_TABLE_EXPR}; + commit; -""" -act = isql_act('db', test_script, substitutions=[('-Effective user is.*', '')]) + connect '{act.db.dsn}' user {tmp_user.name} password '{tmp_user.password}'; + -- All following statements should PASS: + create descending index systable_comm_idx on rdb$relations(rdb$format); + create descending index systable_calc_idx on rdb$relations computed by ( 1 + rdb$format ); + set statistics index systable_comm_idx; + set statistics index systable_calc_idx; -expected_stdout = """ - PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) - SIGN_COUNT 1 - PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) - SIGN_COUNT 1 + select sign(count(*)) as sign_count from rdb$relations where rdb$format < 65537; + select sign(count(*)) as sign_count from rdb$relations where 1 + rdb$format < 65537; - PLAN (RDB$RELATIONS INDEX (SYSTABLE_COMM_IDX)) - SIGN_COUNT 1 - PLAN (RDB$RELATIONS INDEX (SYSTABLE_CALC_IDX)) - SIGN_COUNT 1 -""" + alter index systable_calc_idx inactive; + alter index systable_calc_idx active; -expected_stderr = """ - Statement failed, SQLSTATE = 28000 - unsuccessful metadata update - -CREATE INDEX SYSTABLE_COMM_IDX failed - -no permission for ALTER access to TABLE RDB$RELATIONS -""" + drop index systable_comm_idx; + drop index systable_calc_idx; + commit; -@pytest.mark.version('>=3.0.4') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + """ + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.isql(switches=['-q'], input=test_script, combine_output = True, io_enc = locale.getpreferredencoding()) + assert act.clean_stdout == act.clean_expected_stdout From 7c311062a2b287b7b04c2af22e7583b073490ce6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Thu, 3 Jul 2025 21:34:59 +0300 Subject: [PATCH 1001/1064] Added/Updated tests\bugs\core_5853_test.py: Added substitution to suppress all except sqltype and fields name from SQLDA output. --- tests/bugs/core_5853_test.py | 52 +++++++++++++----------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/tests/bugs/core_5853_test.py b/tests/bugs/core_5853_test.py index c347c14c..dc832c3a 100644 --- a/tests/bugs/core_5853_test.py +++ b/tests/bugs/core_5853_test.py @@ -7,6 +7,10 @@ DESCRIPTION: JIRA: CORE-5853 FBTEST: bugs.core_5853 +NOTES: + [03.07.2025] pzotov + Added substitution to suppress all except sqltype and fields name from SQLDA output. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813 """ import pytest @@ -16,44 +20,24 @@ # version: 3.0 -test_script_1 = """ - set planonly; - select current_time, current_timestamp from rdb$database; +test_script = """ + set list on; + set sqlda_display on; select localtime from rdb$database; select localtimestamp from rdb$database; """ -act_1 = isql_act('db', test_script_1) +act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|sqltype:|name:).)*$',''),('[ \t]+',' ')]) -expected_stdout_1 = """ - PLAN (RDB$DATABASE NATURAL) - PLAN (RDB$DATABASE NATURAL) - PLAN (RDB$DATABASE NATURAL) +expected_stdout = """ + 01: sqltype: 560 TIME scale: 0 subtype: 0 len: 4 + : name: LOCALTIME alias: LOCALTIME + 01: sqltype: 510 TIMESTAMP scale: 0 subtype: 0 len: 8 + : name: LOCALTIMESTAMP alias: LOCALTIMESTAMP """ -@pytest.mark.version('>=2.5.9,<4.0') -def test_1(act_1: Action): - act_1.expected_stdout = expected_stdout_1 - act_1.execute() - assert act_1.clean_stdout == act_1.clean_expected_stdout - -# version: 4.0 - -test_script_2 = """ - set planonly; - select current_time, current_timestamp from rdb$database; - --select localtime from rdb$database; - --select localtimestamp from rdb$database; -""" - -act_2 = isql_act('db', test_script_2) - -expected_stdout_2 = """ - PLAN (RDB$DATABASE NATURAL) -""" - -@pytest.mark.version('>=4.0') -def test_2(act_2: Action): - act_2.expected_stdout = expected_stdout_2 - act_2.execute() - assert act_2.clean_stdout == act_2.clean_expected_stdout +@pytest.mark.version('>=3.0') +def test_2(act: Action): + act.expected_stdout = expected_stdout + act.execute() + assert act.clean_stdout == act.clean_expected_stdout From bdfb03a05dadf2aab2da421415e6891b4ad49dda Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 12:47:59 +0300 Subject: [PATCH 1002/1064] Added/Updated tests\bugs\core_4706_test.py: See notes. Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214 --- tests/bugs/core_4706_test.py | 59 ++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/tests/bugs/core_4706_test.py b/tests/bugs/core_4706_test.py index baaa4980..bdf23d27 100644 --- a/tests/bugs/core_4706_test.py +++ b/tests/bugs/core_4706_test.py @@ -7,32 +7,67 @@ DESCRIPTION: JIRA: CORE-4706 FBTEST: bugs.core_4706 +NOTES: + [04.07.2025] pzotov + Added check for column with maximal possible size = 63 characters. + Added case when column headers are in non-ascii form. + Blobs ID output is suppressed. + Increased min_version to 4.0 + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214 """ import pytest from firebird.qa import * -db = db_factory() +db = db_factory(charset = 'utf8') test_script = """ set blob all; - select cast('a' as blob) a, 1, cast('a' as blob) x2345678901234567890, 2 from rdb$database; + -- select cast('a' as blob) a, 1, cast('a' as blob) x2345678901234567890, 2 from rdb$database; + select + cast('a' as blob) a + ,1 + ,cast('b' as blob) x2345678901234567890 + ,2 + ,cast('c' as blob) x23456789012345678901234567890123456789012345678901234567890123 + ,3 + from rdb$database; + + select + cast('a' as blob) "α" + ,1 + ,cast('b' as blob) "έαισορροπίαθαείναικά" + ,2 + ,cast('c' as blob) "έαισορροπίαθαείναικάτωαπότομηδέαισορροπίαθαείναικάτωαπότομηδέα" + ,3 + from rdb$database; """ -act = isql_act('db', test_script, substitutions=[('=.*', '')]) +substitutions = [ ('\\d:\\d', 'x:x'), ('={3,}', '') ] +act = isql_act('db', substitutions = substitutions) expected_stdout = """ - A CONSTANT X2345678901234567890 CONSTANT - 0:2 1 0:1 2 -A: -a -X2345678901234567890: -a + A CONSTANT X2345678901234567890 CONSTANT X23456789012345678901234567890123456789012345678901234567890123 CONSTANT + x:x 1 x:x 2 x:x 3 + A: + a + X2345678901234567890: + b + X23456789012345678901234567890123456789012345678901234567890123: + c + α CONSTANT έαισορροπίαθαείναικά CONSTANT έαισορροπίαθαείναικάτωαπότομηδέαισορροπίαθαείναικάτωαπότομηδέα CONSTANT + x:x 1 x:x 2 x:x 3 + α: + a + έαισορροπίαθαείναικά: + b + έαισορροπίαθαείναικάτωαπότομηδέαισορροπίαθαείναικάτωαπότομηδέα: + c """ -@pytest.mark.version('>=3.0') +@pytest.mark.intl +@pytest.mark.version('>=4.0') def test_1(act: Action): act.expected_stdout = expected_stdout - act.execute() + act.isql(switches = ['-q'], charset = 'utf8', input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout - From becc7a5348bb92e6d87f1357772c0253356e3cdf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 12:50:57 +0300 Subject: [PATCH 1003/1064] Updated tests\bugs\core_0606_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/core_0606_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bugs/core_0606_test.py b/tests/bugs/core_0606_test.py index 609486ea..d0ebf6bc 100644 --- a/tests/bugs/core_0606_test.py +++ b/tests/bugs/core_0606_test.py @@ -49,7 +49,7 @@ expected_stdout_6x = """ GRANT SELECT ON PUBLIC."t t" TO ROLE "FOR" GRANT "FOR CVC" TO CVC - GRANT USAGE ON SCHEMA PUBLIC TO USER PUBLIC + GRANT USAGE ON SCHEMA PUBLIC TO PUBLIC WHO_AM_I CVC I_M_PLAYING_ROLE FOR CVC Statement failed, SQLSTATE = 42000 From a0a4a268d5c044c5f8f0cf41faed46cd81927f72 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 13:09:47 +0300 Subject: [PATCH 1004/1064] Updated tests\bugs\gh_0310_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_0310_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bugs/gh_0310_test.py b/tests/bugs/gh_0310_test.py index 38a91464..cbcfe677 100644 --- a/tests/bugs/gh_0310_test.py +++ b/tests/bugs/gh_0310_test.py @@ -1741,6 +1741,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME CURRENT_ROLE RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME CURRENT_SCHEMA + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME CURRENT_TIME RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME CURRENT_TIMESTAMP @@ -2327,6 +2329,8 @@ RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME SCROLL RDB$KEYWORD_RESERVED + RDB$KEYWORD_NAME SEARCH_PATH + RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME SECOND RDB$KEYWORD_RESERVED RDB$KEYWORD_NAME SECURITY @@ -2544,7 +2548,7 @@ RDB$KEYWORD_NAME ZONE RDB$KEYWORD_RESERVED - Records affected: 509 + Records affected: 511 """ @pytest.mark.disabled_in_forks From 953ddc90539aa0609986679cedb441756015256c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 14:21:36 +0300 Subject: [PATCH 1005/1064] Added/Updated tests\bugs\gh_3106_test.py: Re-implemented using con.info.get_table_access_stats(), removed trace launch and parsing. Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. --- tests/bugs/gh_3106_test.py | 88 +++++++++++++++----------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/tests/bugs/gh_3106_test.py b/tests/bugs/gh_3106_test.py index 77810f46..1c30d693 100644 --- a/tests/bugs/gh_3106_test.py +++ b/tests/bugs/gh_3106_test.py @@ -3,24 +3,19 @@ """ ID: issue-3106 ISSUE: 3106 -TITLE: Many indexed reads in a compound index with NULLs +TITLE: Indexed reads in a compound index with NULLs present even if record does not exist DESCRIPTION: - BEFORE fix trace log was like this: - ====== - Table Natural Index - ******************************* - RDB$DATABASE 1 - TEST_TABLE 3 <<< this line must NOT present now. - ====== - AFTER fix trace must contain line only for RDB$DATABASE in the table statistics section. - - Confirmed bug on 4.0.0.2451: trace statistics contain line with three indexed reads for test table. - Checked on 4.0.0.2453 SS/CS: all OK, there are no indexed reads on test table in the trace log. JIRA: CORE-2709 FBTEST: bugs.gh_3106 NOTES: [21.06.2022] pzotov + Confirmed bug on 4.0.0.2451: table statistics has three indexed reads for 'TEST' table. Checked on 4.0.1.2692, 5.0.0.509. + + [04.07.2025] pzotov + Re-implemented using con.info.get_table_access_stats(), removed trace launch and parsing. + Confirmed problem on 4.0.0.2451. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import locale @@ -29,68 +24,55 @@ from firebird.qa import * init_script = ''' - recreate table test_table ( + recreate table test ( id1 int, id2 int, id3 int ); commit; - insert into test_table (id1, id2, id3) values (1, 1, null); - insert into test_table (id1, id2, id3) values (1, 2, null); - insert into test_table (id1, id2, id3) values (1, 3, null); - insert into test_table (id1, id2, id3) values (2, 1, null); - insert into test_table (id1, id2, id3) values (2, 2, null); - insert into test_table (id1, id2, id3) values (2, 3, null); + insert into test (id1, id2, id3) values (1, 1, null); + insert into test (id1, id2, id3) values (1, 2, null); + insert into test (id1, id2, id3) values (1, 3, null); + insert into test (id1, id2, id3) values (2, 1, null); + insert into test (id1, id2, id3) values (2, 2, null); + insert into test (id1, id2, id3) values (2, 3, null); commit; - create index test_table_idx1 on test_table (id1,id2,id3); + create index test_idx_compound on test (id1,id2,id3); commit; ''' db = db_factory(init = init_script) - act = python_act('db', substitutions=[('[ \t]+', ' ')]) -FOUND_EXPECTED_TAB_HEAD_MSG = 'Found table statistics header.' -FOUND_EXPECTED_RDB_STAT_MSG = 'Found expected line for rdb$database.' - -expected_stdout_trace = f""" - {FOUND_EXPECTED_TAB_HEAD_MSG} - {FOUND_EXPECTED_RDB_STAT_MSG} -""" - +expected_out = 'EXPECTED' @pytest.mark.trace -@pytest.mark.version('>=4.0') +@pytest.mark.version('>=3.0') def test_1(act: Action, capsys): - trace_cfg_items = [ - 'time_threshold = 0', - 'log_statement_finish = true', - 'print_perf = true', - ] - sql_run=''' - set list on; - select 1 as dummy from rdb$database r left join test_table t on t.id1 = 1 and t.id2 is null; - ''' + with act.db.connect() as con: + idx_reads = 0 + cur = con.cursor() + cur.execute("select rdb$relation_id from rdb$relations where rdb$relation_name = upper('test')") + src_relation_id = cur.fetchone()[0] - with act.trace(db_events = trace_cfg_items, encoding=locale.getpreferredencoding()): - act.isql(input = sql_run, combine_output = True) + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads = -x_table.indexed if x_table.indexed else 0 - p_tablestat_head = re.compile('Table\\s+Natural\\s+Index', re.IGNORECASE) - p_tablestat_must_found = re.compile('rdb\\$database\\s+\\d+', re.IGNORECASE) - p_tablestat_must_miss = re.compile('test_table\\s+\\d+', re.IGNORECASE) + cur.execute('select 1 /* trace_me */ from test where ID1 = 1 and ID2 IS NULL') + data = cur.fetchall() + for x_table in con.info.get_table_access_stats(): + if x_table.table_id == src_relation_id: + idx_reads += x_table.indexed if x_table.indexed else 0 - for line in act.trace_log: - if p_tablestat_head.search(line): - print( FOUND_EXPECTED_TAB_HEAD_MSG ) - elif p_tablestat_must_found.search(line): - print( FOUND_EXPECTED_RDB_STAT_MSG ) - elif p_tablestat_must_miss.search(line): - print( '### FAILED ### found UNEXPECTED line:') - print(line.strip()) + if idx_reads == 0: + print(expected_out) + else: + print(f'UNEXPECTED: {data=}, {idx_reads=} ') - act.expected_stdout = expected_stdout_trace + act.expected_stdout = expected_out act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From c24a0cf7369e4892486aa26d38037cf7ce0828c1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:04:33 +0300 Subject: [PATCH 1006/1064] Added/Updated tests\bugs\gh_3357_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_3357_test.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/tests/bugs/gh_3357_test.py b/tests/bugs/gh_3357_test.py index e73fc608..c700eecc 100644 --- a/tests/bugs/gh_3357_test.py +++ b/tests/bugs/gh_3357_test.py @@ -6,17 +6,20 @@ TITLE: Bad execution plan if some stream depends on multiple streams via a function [CORE2975] NOTES: [04.03.2023] pzotov - 1. Discussed with dimitr, letters 01-mar-2023 18:37 and 04-mar-2023 10:38. - Test must verify that execution plan uses NESTED LOOPS rather than HASH JOIN. - Because of this, tables must be filled with approximately equal volume of data. - Confirmed bug on 3.0.9.33548 (28-dec-2021), plan was: - PLAN HASH (JOIN (T1 INDEX (T1_COL), T2 INDEX (T2_ID)), T3 NATURAL) - 2. Commit related to this test: - https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 - (13.09.2022 19:17, "More complete solution for #3357 and #7118") - One more test that attempts to verify this commit: bugs/gh_7398_test.py - - Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. + 1. Discussed with dimitr, letters 01-mar-2023 18:37 and 04-mar-2023 10:38. + Test must verify that execution plan uses NESTED LOOPS rather than HASH JOIN. + Because of this, tables must be filled with approximately equal volume of data. + Confirmed bug on 3.0.9.33548 (28-dec-2021), plan was: + PLAN HASH (JOIN (T1 INDEX (T1_COL), T2 INDEX (T2_ID)), T3 NATURAL) + 2. Commit related to this test: + https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 + (13.09.2022 19:17, "More complete solution for #3357 and #7118") + One more test that attempts to verify this commit: bugs/gh_7398_test.py + Checked on 5.0.0.970, 4.0.3.2904, 3.0.11.33665. + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -58,12 +61,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (T2_ID), T3 INDEX (T3_ID)) """ +expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."T1" INDEX ("PUBLIC"."T1_COL"), "PUBLIC"."T2" INDEX ("PUBLIC"."T2_ID"), "PUBLIC"."T3" INDEX ("PUBLIC"."T3_ID")) +""" + @pytest.mark.version('>=3.0.9') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 78a41a7c0e34948856b7465fe8b1ffd188f73cd3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:07:05 +0300 Subject: [PATCH 1007/1064] Added/Updated tests\bugs\gh_3810_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_3810_test.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_3810_test.py b/tests/bugs/gh_3810_test.py index 193dcb24..674a2741 100644 --- a/tests/bugs/gh_3810_test.py +++ b/tests/bugs/gh_3810_test.py @@ -6,13 +6,16 @@ TITLE: Wrong or missing IS NULL optimization (regression) [CORE3449] NOTES: [14.04.2023] pzotov - Confirmed poor performance on 3.0.11.33678 (num of fetches = 10'099). - Checked on 3.0.11.33681 -- all fine, fetches differ for less than 20. - + Confirmed poor performance on 3.0.11.33678 (num of fetches = 10'099). + Checked on 3.0.11.33681 -- all fine, fetches differ for less than 20. [22.09.2023] pzotov - Changed name of table to simpler. - Removed usage of index test_fld2 after discuss with Anton Zuev (Red Soft) and dimitr, - see: https://github.com/FirebirdSQL/firebird-qa/pull/19 + Changed name of table to simpler. + Removed usage of index test_fld2 after discuss with Anton Zuev (Red Soft) and dimitr, + see: https://github.com/FirebirdSQL/firebird-qa/pull/19 + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -95,16 +98,23 @@ ); """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST INDEX (TEST_FLD123)) COUNT 0 FETCHES_DIFF OK, expected """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_FLD123")) + COUNT 0 + FETCHES_DIFF OK, expected +""" + @pytest.mark.version('>=3.0.11') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 0f087764a8a9ec3e3ad1cc8f5886d9f084e29598 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:09:46 +0300 Subject: [PATCH 1008/1064] Added/Updated tests\bugs\gh_3812_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_3812_test.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_3812_test.py b/tests/bugs/gh_3812_test.py index e855e4c0..5d806243 100644 --- a/tests/bugs/gh_3812_test.py +++ b/tests/bugs/gh_3812_test.py @@ -6,11 +6,15 @@ TITLE: Query with SP doesn't accept explicit plan [CORE3451] NOTES: [18.02.2023] pzotov - Confirmed problem on 5.0.0.743, got: - Statement failed, SQLSTATE = 42S02 - -Invalid command - -there is no alias or table named TMP_SP1 at this scope level - Checked on 5.0.0.745 - all OK. + Confirmed problem on 5.0.0.743, got: + Statement failed, SQLSTATE = 42S02 + -Invalid command + -there is no alias or table named TMP_SP1 at this scope level + Checked on 5.0.0.745 - all OK. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668. """ import pytest @@ -65,12 +69,16 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ PLAN JOIN (JOIN (TMP_SP1 NATURAL, T1 INDEX (TMP_TBL1_FLD2)), T2 INDEX (TMP_TBL2_FLD1), T3 INDEX (TMP_TBL3_FLD1)) """ +expected_stdout_6x = """ + PLAN JOIN (JOIN ("PUBLIC"."TMP_SP1" NATURAL, "T1" INDEX ("PUBLIC"."TMP_TBL1_FLD2")), "T2" INDEX ("PUBLIC"."TMP_TBL2_FLD1"), "T3" INDEX ("PUBLIC"."TMP_TBL3_FLD1")) +""" + @pytest.mark.version('>=5.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ca4783e68d1979f1195347ee14bf916823857aa3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:24:18 +0300 Subject: [PATCH 1009/1064] Added/Updated tests\bugs\gh_4314_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_4314_test.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_4314_test.py b/tests/bugs/gh_4314_test.py index 581c3be1..adbbb086 100644 --- a/tests/bugs/gh_4314_test.py +++ b/tests/bugs/gh_4314_test.py @@ -7,7 +7,12 @@ DESCRIPTION: NOTES: [20.08.2024] pzotov - Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. + Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. + [26.06.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + """ import locale import re @@ -92,7 +97,7 @@ def test_1(act: Action, capsys): ps = cur.prepare(test_sql) print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - expected_stdout = """ + expected_stdout_5x = """ Select Expression ....-> Filter ........-> Nested Loop Join (outer) @@ -117,6 +122,32 @@ def test_1(act: Action, capsys): ....................-> Bitmap ........................-> Index "RF_REL_NAME" Range Scan (full match) """ - act.expected_stdout = expected_stdout + + expected_stdout_6x = """ + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Filter + ................-> Table "PUBLIC"."RR" as "PUBLIC"."V" "R" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."RR_ID" Range Scan (upper bound: 1/1) + ............-> Filter + ................-> Table "PUBLIC"."RF" as "PUBLIC"."V" "PUBLIC"."RF" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."RF_REL_NAME" Range Scan (full match) + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Filter + ................-> Table "PUBLIC"."RR" as "D" "R" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."RR_ID" Range Scan (upper bound: 1/1) + ............-> Filter + ................-> Table "PUBLIC"."RF" as "D" "PUBLIC"."RF" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."RF_REL_NAME" 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 From 0f5ee23f17daef5fff76f90bdf8d86e1b41c1754 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:28:23 +0300 Subject: [PATCH 1010/1064] Added/Updated tests\bugs\gh_4954_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_4954_test.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_4954_test.py b/tests/bugs/gh_4954_test.py index 502ffdf5..8d283451 100644 --- a/tests/bugs/gh_4954_test.py +++ b/tests/bugs/gh_4954_test.py @@ -7,8 +7,12 @@ DESCRIPTION: NOTES: [21.08.2024] pzotov - Confirmed bug on 2.1.7.18553. No such problem on 2.5.927156. - Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. + Confirmed bug on 2.1.7.18553. No such problem on 2.5.927156. + Checked on 6.0.0.438, 5.0.2.1479, 4.0.6.3142, 3.0.12.33784. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest from firebird.qa import * @@ -110,7 +114,7 @@ def test_1(act: Action, capsys): ps = cur.prepare(test_sql) print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - expected_plan_4x = """ + expected_stdout_4x = """ Select Expression ....-> Singularity Check ........-> First N Records @@ -127,7 +131,8 @@ def test_1(act: Action, capsys): Select Expression ....-> Table "T3" Full Scan """ - expected_plan_5x = """ + + expected_stdout_5x = """ Sub-query ....-> Singularity Check ........-> First N Records @@ -145,6 +150,26 @@ def test_1(act: Action, capsys): Select Expression ....-> Table "T3" Full Scan """ - act.expected_stdout = expected_plan_4x if act.is_version('<5') else expected_plan_5x + + expected_stdout_6x = """ + Sub-query + ....-> Singularity Check + ........-> First N Records + ............-> Filter + ................-> Filter + ....................-> Union + ........................-> Filter + ............................-> Table "PUBLIC"."T1" as "PUBLIC"."V1" "PUBLIC"."T1" Access By ID + ................................-> Bitmap + ....................................-> Index "PUBLIC"."T1_UK1" Unique Scan + ........................-> Filter + ............................-> Table "PUBLIC"."T2" as "PUBLIC"."V1" "PUBLIC"."T2" Access By ID + ................................-> Bitmap + ....................................-> Index "PUBLIC"."T2_UK1" Unique Scan + Select Expression + ....-> Table "PUBLIC"."T3" Full Scan + """ + + act.expected_stdout = expected_stdout_4x if act.is_version('<5') else 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 From 0d60a354004a75c5d761701202ccdb3f8165a684 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:39:24 +0300 Subject: [PATCH 1011/1064] Added/Updated tests\bugs\gh_5009_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_5009_test.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_5009_test.py b/tests/bugs/gh_5009_test.py index 24f4aab5..1d520115 100644 --- a/tests/bugs/gh_5009_test.py +++ b/tests/bugs/gh_5009_test.py @@ -8,8 +8,13 @@ JIRA: CORE-4701 NOTES: [02.11.2024] pzotov - Confirmed bug on 3.0.13.33794. - Checked on 4.0.6.3165, 5.0.2.1551, 6.0.0.415 + Confirmed bug on 3.0.13.33794. + Checked on 4.0.6.3165, 5.0.2.1551, 6.0.0.415 + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. + """ import pytest @@ -50,7 +55,7 @@ def test_1(act: Action, capsys): act.execute(combine_output = True) - act.expected_stdout = """ + expected_stdout_5x = """ PLAN (G NATURAL) F_NATREADS 3 Records affected: 1 @@ -59,6 +64,16 @@ def test_1(act: Action, capsys): Records affected: 1 """ + expected_stdout_6x = """ + PLAN ("G" NATURAL) + F_NATREADS 3 + Records affected: 1 + PLAN ("G" INDEX ("PUBLIC"."G_IND")) + F_IDXREADS 3 + Records affected: 1 + """ + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + with act.connect_server() as srv: srv.database.validate(database = act.db.db_path) validate_err = '\n'.join( [line for line in srv if 'ERROR' in line.upper()] ) From 10470dd51a81d43085dbc006daa67cf4d8a3925a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 16:42:56 +0300 Subject: [PATCH 1012/1064] Added/Updated tests\bugs\gh_6778_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6778_test.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_6778_test.py b/tests/bugs/gh_6778_test.py index 1b623897..995ccc2f 100644 --- a/tests/bugs/gh_6778_test.py +++ b/tests/bugs/gh_6778_test.py @@ -11,6 +11,11 @@ Checked on: 4.0.0.2448 - works fine. No errors must be during execution of this code. FBTEST: bugs.gh_6778 +NOTES: + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -123,11 +128,20 @@ PLAN JOIN (C A2 NATURAL, C A1 INDEX (IA1)) """ +fb6_expected_stdout = """ + -- line, column + PLAN JOIN ("C" "PUBLIC"."A1" NATURAL, "C" "PUBLIC"."A2" INDEX ("PUBLIC"."IA2")) + -- line, column + PLAN JOIN ("C" "PUBLIC"."A2" NATURAL, "C" "PUBLIC"."A1" INDEX ("PUBLIC"."IA1")) +""" + act = python_act('db', substitutions=[('-- line(:)?\\s+\\d+,\\s+col(umn)?(:)?\\s+\\d+', '-- line, column')]) @pytest.mark.version('>=4.0') def test_1(act: Action): + test_script = fb5_test_script if act.is_version('>=5') else fb4_test_script - act.expected_stdout = fb5_expected_stdout if act.is_version('>=5') else fb4_expected_stdout - act.isql(switches=['-q'], input=test_script) + expected_stdout = fb4_expected_stdout if act.is_version('<5') else fb5_expected_stdout if act.is_version('<6') else fb6_expected_stdout + act.expected_stdout = expected_stdout + act.isql(switches=['-q'], input=test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 936be44681eaa8986798822a4a60ee30d222c81d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:22:22 +0300 Subject: [PATCH 1013/1064] Added/Updated tests\bugs\gh_6782_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6782_test.py | 48 +++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_6782_test.py b/tests/bugs/gh_6782_test.py index cc7921e6..b09c0c9a 100644 --- a/tests/bugs/gh_6782_test.py +++ b/tests/bugs/gh_6782_test.py @@ -22,11 +22,16 @@ Test parses trace log and search there lines with names of known procedures/functions and then checks presence of lines with number of fetched records (for selectable procedures) and additional statistics ('fetches/reads/writes/marks'). +FBTEST: bugs.gh_6782 NOTES: [30.06.2022] pzotov - Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.509. - -FBTEST: bugs.gh_6782 + Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.509. + [04.07.2025] pzotov + Changed list of patterns to find name of procedures / functions (standalone / packaged): + we have to take in account name of SQL schema and presense of double quotes in 6.x. + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import locale @@ -142,7 +147,7 @@ act = python_act('db') -expected_stdout_trace = """ +expected_stdout_5x = """ Procedure STANDALONE_SELECTABLE_SP: FOUND line with number of fetched records FOUND line with execution statistics @@ -167,6 +172,31 @@ FOUND line with execution statistics """ +expected_stdout_6x = """ + Procedure "PUBLIC"."STANDALONE_SELECTABLE_SP": + FOUND line with number of fetched records + FOUND line with execution statistics + + Function "PUBLIC"."STANDALONE_FUNC": + FOUND line with execution statistics + + Procedure "PUBLIC"."STANDALONE_NONSELECTED_SP": + FOUND line with execution statistics + + Procedure "PUBLIC"."PG_TEST"."PACKAGED_SELECTABLE_SP": + FOUND line with number of fetched records + FOUND line with execution statistics + + Function "PUBLIC"."PG_TEST"."PACKAGED_FUNC": + FOUND line with execution statistics + + Procedure "PUBLIC"."PG_TEST"."PACKAGED_NONSELECTED_SP": + FOUND line with execution statistics + + Procedure "PUBLIC"."SP_MAIN": + FOUND line with execution statistics +""" + @pytest.mark.trace @pytest.mark.version('>=3.0.8') def test_1(act: Action, capsys): @@ -189,8 +219,10 @@ def test_1(act: Action, capsys): allowed_patterns = \ ( - r'Procedure\s+(STANDALONE_SELECTABLE_SP:|STANDALONE_NONSELECTED_SP:|PG_TEST.PACKAGED_SELECTABLE_SP:|PG_TEST.PACKAGED_NONSELECTED_SP:|SP_MAIN:)' - ,r'Function\s+(STANDALONE_FUNC:|PG_TEST.PACKAGED_FUNC:)' + r'Procedure\s+("PUBLIC".)?(")?(STANDALONE_SELECTABLE_SP|STANDALONE_NONSELECTED_SP|SP_MAIN)(")?:' + ,r'Function\s+("PUBLIC".)?(")?STANDALONE_FUNC(")?:' + ,r'Procedure\s+("PUBLIC".)?(")?PG_TEST(")?.(")?(PACKAGED_SELECTABLE_SP|PACKAGED_NONSELECTED_SP)(")?:' + ,r'Function\s+("PUBLIC".)?(")?PG_TEST(")?.(")?(PACKAGED_FUNC)(")?:' ,r'\d+\s+record(s|\(s\))?\s+fetched' ,r'\s+\d+\s+ms(,)?' ) @@ -199,7 +231,7 @@ def test_1(act: Action, capsys): for line in act.trace_log: if line.strip(): - #print('>'+line.strip()+'<', act.match_any(line, allowed_patterns)) + # print('>'+line.strip()+'<', act.match_any(line, allowed_patterns)) if act.match_any(line, allowed_patterns): if ' ms' in line and 'fetch' in line: print('FOUND line with execution statistics') @@ -208,6 +240,6 @@ def test_1(act: Action, capsys): else: print(line) - act.expected_stdout = expected_stdout_trace + 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 From bacba3246952b82d516983a2cf2c5af55c6b2d84 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:25:49 +0300 Subject: [PATCH 1014/1064] Added/Updated tests\bugs\gh_6797_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_6797_test.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_6797_test.py b/tests/bugs/gh_6797_test.py index 1b357a44..a21ee3bc 100644 --- a/tests/bugs/gh_6797_test.py +++ b/tests/bugs/gh_6797_test.py @@ -13,6 +13,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -33,13 +36,14 @@ act = isql_act('db', test_script, substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')]) -expected_stdout = """ - 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 1 charset: 1 OCTETS - 02: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 1 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + 02: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 + """ act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 776e95c19299f84d30221304ef5d7f13e9123897 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:27:40 +0300 Subject: [PATCH 1015/1064] Added/Updated tests\bugs\gh_6812_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_6812_test.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_6812_test.py b/tests/bugs/gh_6812_test.py index ec761db5..dab140f6 100644 --- a/tests/bugs/gh_6812_test.py +++ b/tests/bugs/gh_6812_test.py @@ -11,6 +11,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -26,15 +29,15 @@ act = isql_act('db', test_script, substitutions=[('^((?!(SQLSTATE|sqltype|enc)).)*$', ''), ('[ \t]+', ' ')]) -expected_stdout = """ - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 ASCII - : name: HEX_ENCODE alias: enc_01 - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 ASCII - : name: BASE64_ENCODE alias: enc_02 -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: HEX_ENCODE alias: enc_01 + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: BASE64_ENCODE alias: enc_02 + """ act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1c29b99aefafa3bbe395f10504b008c0b675d58e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:29:11 +0300 Subject: [PATCH 1016/1064] Added/Updated tests\bugs\gh_6816_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_6816_test.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_6816_test.py b/tests/bugs/gh_6816_test.py index 1ce903ed..1103cac7 100644 --- a/tests/bugs/gh_6816_test.py +++ b/tests/bugs/gh_6816_test.py @@ -11,6 +11,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -29,15 +32,16 @@ act = isql_act('db', test_script, substitutions=[('^((?!(SQLSTATE|sqltype)).)*$', ''), ('[ \t]+', ' ')]) -expected_stdout = """ - 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 10 charset: 2 ASCII - 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 8 charset: 2 ASCII - 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 3 charset: 1 OCTETS - 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 2 charset: 1 OCTETS -""" - @pytest.mark.version('>=4.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 10 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 8 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 3 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + 02: sqltype: 448 VARYING scale: 0 subtype: 0 len: 2 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + """ act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 2f553cf1ae5761236694f58e550dde11dda3b946 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:31:42 +0300 Subject: [PATCH 1017/1064] Added/Updated tests\bugs\gh_6825_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6825_test.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_6825_test.py b/tests/bugs/gh_6825_test.py index 118f041a..52307272 100644 --- a/tests/bugs/gh_6825_test.py +++ b/tests/bugs/gh_6825_test.py @@ -6,6 +6,11 @@ TITLE: Correct error message for DROP VIEW DESCRIPTION: FBTEST: bugs.gh_6825 +NOTES: + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -27,7 +32,7 @@ act = isql_act('db', test_script, substitutions=[('(-)?Effective user is.*', '')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update -DROP VIEW V1 failed @@ -35,8 +40,16 @@ -Effective user is TMP$GH_6825 """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -DROP VIEW "PUBLIC"."V1" failed + -no permission for DROP access to VIEW "PUBLIC"."V1" +""" + @pytest.mark.version('>=3.0.8') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 220ec12281013fbeb74307cf311e5d914bd40ed4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:34:08 +0300 Subject: [PATCH 1018/1064] Added/Updated tests\bugs\gh_6869_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_6869_test.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/bugs/gh_6869_test.py b/tests/bugs/gh_6869_test.py index 11fc54e9..1860a4a0 100644 --- a/tests/bugs/gh_6869_test.py +++ b/tests/bugs/gh_6869_test.py @@ -6,8 +6,12 @@ TITLE: Domain CHECK-expression can be ignored when we DROP objects that are involved in it NOTES: [25.02.2023] pzotov - Confirmed bug on 5.0.0.520. - Checked on 5.0.0.959 - all OK. + Confirmed bug on 5.0.0.520. + Checked on 5.0.0.959 - all OK. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668. """ import pytest @@ -43,7 +47,7 @@ act = isql_act('db', test_script) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = 42000 unsuccessful metadata update -cannot delete @@ -57,8 +61,21 @@ -there are 1 dependencies """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."TEST"."I" + -there are 1 dependencies + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."TEST"."I" + -there are 1 dependencies +""" + @pytest.mark.version('>=5.0') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From d9c10ea53a06cb98ea0b84927281ca2532e171b4 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:38:35 +0300 Subject: [PATCH 1019/1064] Added/Updated tests\bugs\gh_6873_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6873_test.py | 60 +++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_6873_test.py b/tests/bugs/gh_6873_test.py index 2a089dac..9ee4a331 100644 --- a/tests/bugs/gh_6873_test.py +++ b/tests/bugs/gh_6873_test.py @@ -6,6 +6,11 @@ TITLE: SIMILAR TO does not use index when pattern starts with non-wildcard character (in contrary to LIKE) DESCRIPTION: FBTEST: bugs.gh_6873 +NOTES: + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668. """ import pytest @@ -102,9 +107,10 @@ """ -act = isql_act('db', test_script) +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) -expected_stdout = """ +expected_stdout_5x = """ PLAN (TEST INDEX (TEST_X1_ASC)) ID 2 ID 4 @@ -166,8 +172,54 @@ ID 2 """ +expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X1_ASC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X1_ASC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X1_ASC")) + ID 2 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y1_DEC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y1_DEC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y1_DEC")) + ID 2 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X2_ASC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X2_ASC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X2_ASC")) + ID 2 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y2_DEC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y2_DEC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y2_DEC")) + ID 2 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X3_ASC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X3_ASC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_X3_ASC")) + ID 2 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y3_DEC")) + ID 2 + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y3_DEC")) + ID 4 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_Y3_DEC")) + ID 2 +""" + @pytest.mark.version('>=5.0') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute() + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 3c89258ef3eb5f27a3146ceed488de11c7d5e813 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:40:58 +0300 Subject: [PATCH 1020/1064] Added/Updated tests\bugs\gh_6903_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6903_test.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_6903_test.py b/tests/bugs/gh_6903_test.py index f1f0cda9..72c06864 100644 --- a/tests/bugs/gh_6903_test.py +++ b/tests/bugs/gh_6903_test.py @@ -6,6 +6,11 @@ TITLE: Unable to create ICU-based collation with locale keywords DESCRIPTION: FBTEST: bugs.gh_6903 +NOTES: + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -46,15 +51,23 @@ act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) -expected_stderr = """ +expected_stdout_5x = """ Statement failed, SQLSTATE = HY000 unsuccessful metadata update -CREATE COLLATION UNICODE_BAD_01 failed -Invalid collation attributes """ +expected_stdout_6x = """ + Statement failed, SQLSTATE = HY000 + unsuccessful metadata update + -CREATE COLLATION "PUBLIC"."UNICODE_BAD_01" failed + -Invalid collation attributes +""" + @pytest.mark.version('>=4.0.1') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 75b3c8986f773a5282a4c9efdd494b4057c2edb7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 17:44:12 +0300 Subject: [PATCH 1021/1064] Added/Updated tests\bugs\gh_6963_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6963_test.py | 40 ++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/tests/bugs/gh_6963_test.py b/tests/bugs/gh_6963_test.py index 6d1a6bff..5a18ed4a 100644 --- a/tests/bugs/gh_6963_test.py +++ b/tests/bugs/gh_6963_test.py @@ -6,6 +6,11 @@ TITLE: grant references not working DESCRIPTION: FBTEST: bugs.gh_6963 +NOTES: + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -83,31 +88,42 @@ act = isql_act('db', test_script) -expected_stdout = """ +expected_stdout_5x = """ + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TMAIN_A failed + -no permission for ALTER access to TABLE TMAIN_A + -Effective user is TMP$GH6963 + Statement failed, SQLSTATE = 28000 + unsuccessful metadata update + -ALTER TABLE TMAIN_A failed + -no permission for ALTER access to TABLE TMAIN_A + -Effective user is TMP$GH6963 RDB$RELATION_NAME TDETL_A_WITHOUT_CASC RDB$RELATION_NAME TDETL_A_WITH_CASC RDB$RELATION_NAME TMAIN_A Records affected: 3 """ -expected_stderr = """ +expected_stdout_6x = """ Statement failed, SQLSTATE = 28000 unsuccessful metadata update - -ALTER TABLE TMAIN_A failed - -no permission for ALTER access to TABLE TMAIN_A + -ALTER TABLE "PUBLIC"."TMAIN_A" failed + -no permission for ALTER access to TABLE "PUBLIC"."TMAIN_A" -Effective user is TMP$GH6963 - Statement failed, SQLSTATE = 28000 unsuccessful metadata update - -ALTER TABLE TMAIN_A failed - -no permission for ALTER access to TABLE TMAIN_A + -ALTER TABLE "PUBLIC"."TMAIN_A" failed + -no permission for ALTER access to TABLE "PUBLIC"."TMAIN_A" -Effective user is TMP$GH6963 + RDB$RELATION_NAME TDETL_A_WITHOUT_CASC + RDB$RELATION_NAME TDETL_A_WITH_CASC + RDB$RELATION_NAME TMAIN_A + Records affected: 3 """ @pytest.mark.version('>=4.0.1') def test_1(act: Action): - act.expected_stdout = expected_stdout - act.expected_stderr = expected_stderr - act.execute() - assert (act.clean_stderr == act.clean_expected_stderr and - act.clean_stdout == act.clean_expected_stdout) + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From ccc273846950daea61f9806ee88e98abf973972e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 18:02:33 +0300 Subject: [PATCH 1022/1064] Added/Updated tests\bugs\gh_6992_test.py: Re-implemented: queries and comments/explanations to be displayed in expected_out (using f-notation). Output is organized to be more suitable for reading and search for mismatches (see 'qry_map' dict). Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_6992_test.py | 250 +++++++++++++++++++++++++++++-------- 1 file changed, 201 insertions(+), 49 deletions(-) diff --git a/tests/bugs/gh_6992_test.py b/tests/bugs/gh_6992_test.py index eacfcb38..a0ce22c0 100644 --- a/tests/bugs/gh_6992_test.py +++ b/tests/bugs/gh_6992_test.py @@ -5,16 +5,18 @@ ISSUE: 6992 TITLE: Transform OUTER joins into INNER ones if the WHERE condition violates the outer join rules NOTES: - [17.02.2023] pzotov - Initial implementation. Additional tests will be added further. + [04.07.2025] pzotov + Re-implemented: queries and comments/explanations to be displayed in expected_out (using f-notation). + Output is organized to be more suitable for reading and search for mismatches (see 'qry_map' dict). + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.892; 5.0.3.1668; 4.0.6.3214. """ import pytest from firebird.qa import * -db = db_factory() - -test_script = """ +init_script = """ set bail on; recreate table tmain( id int primary key using index tmain_pk @@ -52,7 +54,11 @@ set statistics index tmain_pk; set statistics index tdetl_a_fk; set statistics index tdetl_b_fk; + commit; +""" +db = db_factory(init = init_script) +test_script = """ set planonly; set explain on; @@ -92,50 +98,196 @@ ; """ -act = isql_act('db', test_script) - -expected_stdout = """ - Select Expression - -> Filter - -> Nested Loop Join (outer) - -> Table "TMAIN" as "M1" Full Scan - -> Filter - -> Table "TDETL_A" as "D1" Access By ID - -> Bitmap - -> Index "TDETL_A_FK" Range Scan (full match) - - Select Expression - -> Nested Loop Join (inner) - -> Filter - -> Table "TMAIN" as "M2" Access By ID - -> Bitmap - -> Index "TMAIN_PK" Unique Scan - -> Filter - -> Table "TDETL_A" as "D2" Access By ID - -> Bitmap - -> Index "TDETL_A_FK" Range Scan (full match) - - Select Expression - -> Filter - -> Nested Loop Join (outer) - -> Table "TMAIN" as "M3" Full Scan - -> Filter - -> Table "TDETL_A" as "D3" Access By ID - -> Bitmap - -> Index "TDETL_A_FK" Range Scan (full match) - - Select Expression - -> Filter - -> Nested Loop Join (outer) - -> Table "TMAIN" as "M4" Full Scan - -> Filter - -> Table "TDETL_B" as "D4" Access By ID - -> Bitmap - -> Index "TDETL_B_FK" Range Scan (full match) -""" +qry_map = { + 1000 : + ( + """ + select * + from tmain m1 + left join tdetl_a d1 on m1.id = d1.pid + where d1.pid is null + """ + , + """ + Must NOT be transformed because we make here ANTI-JOIN. + Outer join is the only way to get proper result here. + """ + ) + , + 2000 : + ( + """ + select * + from tmain m2 + left join tdetl_a d2 on m2.id = d2.pid + where d2.pid = 0 + """ + , + """ + This MUST be transformed to INNER join because WHERE expression effectively will skip nulls. + See also issue in the ticket: + "regular comparisons that ignore NULLs by their nature, will cause the LEFT->INNER transformation" + """ + ) + + , + 3000 : + ( + """ + select * + from tmain m3 + left join tdetl_a d3 on m3.id = d3.pid + where d3.pid is not null + """ + , + """ + This must NOT be transformed, see ticket: + "checks for NULL, e.g. WHERE T2.ID IS NOT NULL ..., would not transform LEFT into INNER" + """ + ) + , + 4000 : + ( + """ + select * + from tmain m4 + left join tdetl_b d4 on m4.id = d4.pid + where d4.pid is not null + + """ + , + """ + This must NOT be transformed, reason is the same: + "checks for NULL, e.g. WHERE T2.ID IS NOT NULL ..., would not transform LEFT into INNER" + NB: the fact that column tdetl_b.pid is declared as NOT NULL is ignored here. + This limitation seems redunant here. + """ + + ) +} + +act = python_act('db') + +#----------------------------------------------------------- + +def replace_leading(source, char="."): + stripped = source.lstrip() + return char * (len(source) - len(stripped)) + stripped + +#----------------------------------------------------------- @pytest.mark.version('>=5.0') -def test_1(act: Action): - act.expected_stdout = expected_stdout - act.execute(combine_output = True) +def test_1(act: Action, capsys): + with act.db.connect() as con: + cur = con.cursor() + for qry_idx, qry_data in qry_map.items(): + test_sql, qry_comment = qry_data[:2] + ps, rs = None, None + try: + cur = con.cursor() + ps = cur.prepare(test_sql) + + print(qry_comment) + # Print explained plan with padding eash line by dots in order to see indentations: + print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) + except DatabaseError as e: + print(e.__str__()) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_out_5x = f""" + {qry_map.get(1000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "TMAIN" as "M1" Full Scan + ............-> Filter + ................-> Table "TDETL_A" as "D1" Access By ID + ....................-> Bitmap + ........................-> Index "TDETL_A_FK" Range Scan (full match) + + {qry_map.get(2000)[1]} + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "TMAIN" as "M2" Access By ID + ................-> Bitmap + ....................-> Index "TMAIN_PK" Unique Scan + ........-> Filter + ............-> Table "TDETL_A" as "D2" Access By ID + ................-> Bitmap + ....................-> Index "TDETL_A_FK" Range Scan (full match) + + {qry_map.get(3000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "TMAIN" as "M3" Full Scan + ............-> Filter + ................-> Table "TDETL_A" as "D3" Access By ID + ....................-> Bitmap + ........................-> Index "TDETL_A_FK" Range Scan (full match) + + {qry_map.get(4000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "TMAIN" as "M4" Full Scan + ............-> Filter + ................-> Table "TDETL_B" as "D4" Access By ID + ....................-> Bitmap + ........................-> Index "TDETL_B_FK" Range Scan (full match) + """ + + expected_out_6x = f""" + + {qry_map.get(1000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "PUBLIC"."TMAIN" as "M1" Full Scan + ............-> Filter + ................-> Table "PUBLIC"."TDETL_A" as "D1" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."TDETL_A_FK" Range Scan (full match) + + {qry_map.get(2000)[1]} + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "PUBLIC"."TMAIN" as "M2" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TMAIN_PK" Unique Scan + ........-> Filter + ............-> Table "PUBLIC"."TDETL_A" as "D2" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TDETL_A_FK" Range Scan (full match) + + {qry_map.get(3000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "PUBLIC"."TMAIN" as "M3" Full Scan + ............-> Filter + ................-> Table "PUBLIC"."TDETL_A" as "D3" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."TDETL_A_FK" Range Scan (full match) + + {qry_map.get(4000)[1]} + Select Expression + ....-> Filter + ........-> Nested Loop Join (outer) + ............-> Table "PUBLIC"."TMAIN" as "M4" Full Scan + ............-> Filter + ................-> Table "PUBLIC"."TDETL_B" as "D4" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."TDETL_B_FK" Range Scan (full match) + """ + + act.expected_stdout = expected_out_5x if act.is_version('<6') else expected_out_6x + act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From d499bdf3363d6bd25065e8103c57f17c6c1de64e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:15:39 +0300 Subject: [PATCH 1023/1064] Added/Updated tests\bugs\gh_7046_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7046_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_7046_test.py b/tests/bugs/gh_7046_test.py index 38cacb77..9067540a 100644 --- a/tests/bugs/gh_7046_test.py +++ b/tests/bugs/gh_7046_test.py @@ -23,7 +23,6 @@ "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" 3. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf (for LINUX this equality is case-sensitive, even when aliases are compared!) - Checked on 5.0.0.958 [26.06.2023] pzotov @@ -31,8 +30,11 @@ https://github.com/FirebirdSQL/firebird/commit/15b0b297dcde81cc5e1c38cbd4ea761e27f442bd Added check for this ability. Also, comment text now is non-ascii (decided to use parts of 'lorem ipsum' encoded in armenian and georgian) - Checked on 5.0.0.1087 + + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import os @@ -58,6 +60,7 @@ tmp_file = temp_file('tmp_gh_7046-ddl.sql') fn_meta_log = temp_file('tmp_gh_7046-meta.log') +@pytest.mark.intl @pytest.mark.version('>=5.0') def test_1(act: Action, tmp_file: Path, fn_meta_log: Path, capsys): @@ -203,10 +206,12 @@ def test_1(act: Action, tmp_file: Path, fn_meta_log: Path, capsys): elif 'SQLSTATE' in line: print('UNEXPECTED ERROR: ',line) + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' act.expected_stdout = u""" CREATE MAPPING %(MAPPING_NAME)s USING PLUGIN CREATE OR ALTER GLOBAL MAPPING %(MAPPING_NAME)s USING PLUGIN - COMMENT ON VIEW V_MAP_INFO IS '%(VIEW_COMMENT)s'; + COMMENT ON VIEW %(SQL_SCHEMA_PREFIX)sV_MAP_INFO IS '%(VIEW_COMMENT)s'; COMMENT ON MAPPING TRUSTED_AUTH_7046 IS '%(MAPPING_COMMENT)s'; COMMENT ON GLOBAL MAPPING TRUSTED_AUTH_7046 IS '%(MAPPING_COMMENT)s'; """ % locals() From 3acc8f1af0d407792c4808ca45b82a3a3f48a574 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:21:00 +0300 Subject: [PATCH 1024/1064] Added/Updated tests\bugs\gh_7050_test.py: Added 'SQL_SCHEMA_*_PREFIX' variables to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7050_test.py | 194 +++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 94 deletions(-) diff --git a/tests/bugs/gh_7050_test.py b/tests/bugs/gh_7050_test.py index 3239c428..4eb1a99a 100644 --- a/tests/bugs/gh_7050_test.py +++ b/tests/bugs/gh_7050_test.py @@ -9,6 +9,10 @@ Test based on example provided in doc/README.monitoring_tables Probably much useful test will be implemened later (with join mon$memory_usage etc). Checked on 6.0.0.213, 5.0.1.1307. + + [04.07.2025] pzotov + Added 'SQL_SCHEMA_*_PREFIX' variables to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668. """ import pytest @@ -111,102 +115,104 @@ act = isql_act('db', test_script, substitutions = subs) -expected_stdout = """ - N_FACTORIAL 120 - MON_STTM_ID - MON_CSTM_ID - MON_STAT_ID - MON_STATE 1 - MON_SQL_TEXT_BLOB_ID - select n_factorial from fact_static_psql(5) - MON_EXPLAINED_PLAN_BLOB_ID - Select Expression - -> Procedure "FACT_STATIC_PSQL" Scan - Records affected: 1 - - - MON_CSTM_ID - MON_SQL_TEXT_BLOB_ID - select n_factorial from fact_static_psql(5) - MON_EXPLAINED_PLAN_BLOB_ID - Select Expression - -> Procedure "FACT_STATIC_PSQL" Scan - MON_OBJ_NAME - MON_OBJ_TYPE - MON_PKG_NAME - MON_STAT_ID - - MON_CSTM_ID - MON_SQL_TEXT_BLOB_ID - MON_EXPLAINED_PLAN_BLOB_ID - Select Expression - -> Singularity Check - -> Procedure "FACT_STATIC_PSQL" Scan - Select Expression - -> Singularity Check - -> Table "MON$DATABASE" Full Scan - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_PKG_NAME - MON_STAT_ID - Records affected: 2 - - - MON_STTM_ID - MON_CALL_ID 192 - MON_CALLER_ID - MON_STAT_ID - MON_CSTM_ID - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_SRC_ROW 8 - MON_SRC_COL 17 - - MON_STTM_ID - MON_CALL_ID 193 - MON_CALLER_ID 192 - MON_STAT_ID - MON_CSTM_ID - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_SRC_ROW 8 - MON_SRC_COL 17 - - MON_STTM_ID - MON_CALL_ID 194 - MON_CALLER_ID 193 - MON_STAT_ID - MON_CSTM_ID - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_SRC_ROW 8 - MON_SRC_COL 17 - - MON_STTM_ID - MON_CALL_ID 195 - MON_CALLER_ID 194 - MON_STAT_ID - MON_CSTM_ID - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_SRC_ROW 8 - MON_SRC_COL 17 - - MON_STTM_ID - MON_CALL_ID 196 - MON_CALLER_ID 195 - MON_STAT_ID - MON_CSTM_ID - MON_OBJ_NAME FACT_STATIC_PSQL - MON_OBJ_TYPE 5 - MON_SRC_ROW 15 - MON_SRC_COL 13 - Records affected: 5 - -""" - @pytest.mark.version('>=5.0') def test_1(act: Action): + + SQL_SCHEMA_PUBLIC_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + SQL_SCHEMA_SYSTEM_PREFIX = '' if act.is_version('<6') else '"SYSTEM".' + expected_stdout = f""" + N_FACTORIAL 120 + MON_STTM_ID + MON_CSTM_ID + MON_STAT_ID + MON_STATE 1 + MON_SQL_TEXT_BLOB_ID + select n_factorial from fact_static_psql(5) + MON_EXPLAINED_PLAN_BLOB_ID + Select Expression + -> Procedure {SQL_SCHEMA_PUBLIC_PREFIX}"FACT_STATIC_PSQL" Scan + Records affected: 1 + + + MON_CSTM_ID + MON_SQL_TEXT_BLOB_ID + select n_factorial from fact_static_psql(5) + MON_EXPLAINED_PLAN_BLOB_ID + Select Expression + -> Procedure {SQL_SCHEMA_PUBLIC_PREFIX}"FACT_STATIC_PSQL" Scan + MON_OBJ_NAME + MON_OBJ_TYPE + MON_PKG_NAME + MON_STAT_ID + + MON_CSTM_ID + MON_SQL_TEXT_BLOB_ID + MON_EXPLAINED_PLAN_BLOB_ID + Select Expression + -> Singularity Check + -> Procedure {SQL_SCHEMA_PUBLIC_PREFIX}"FACT_STATIC_PSQL" Scan + Select Expression + -> Singularity Check + -> Table {SQL_SCHEMA_SYSTEM_PREFIX}"MON$DATABASE" Full Scan + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_PKG_NAME + MON_STAT_ID + Records affected: 2 + + + MON_STTM_ID + MON_CALL_ID 192 + MON_CALLER_ID + MON_STAT_ID + MON_CSTM_ID + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_SRC_ROW 8 + MON_SRC_COL 17 + + MON_STTM_ID + MON_CALL_ID 193 + MON_CALLER_ID 192 + MON_STAT_ID + MON_CSTM_ID + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_SRC_ROW 8 + MON_SRC_COL 17 + + MON_STTM_ID + MON_CALL_ID 194 + MON_CALLER_ID 193 + MON_STAT_ID + MON_CSTM_ID + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_SRC_ROW 8 + MON_SRC_COL 17 + + MON_STTM_ID + MON_CALL_ID 195 + MON_CALLER_ID 194 + MON_STAT_ID + MON_CSTM_ID + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_SRC_ROW 8 + MON_SRC_COL 17 + + MON_STTM_ID + MON_CALL_ID 196 + MON_CALLER_ID 195 + MON_STAT_ID + MON_CSTM_ID + MON_OBJ_NAME FACT_STATIC_PSQL + MON_OBJ_TYPE 5 + MON_SRC_ROW 15 + MON_SRC_COL 13 + Records affected: 5 + """ + act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 6d4e2b86a3f30eb423a6f091c164ca626ea36659 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:24:00 +0300 Subject: [PATCH 1025/1064] Added/Updated tests\bugs\gh_7062_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7062_test.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/bugs/gh_7062_test.py b/tests/bugs/gh_7062_test.py index 1be3dcfb..ca29275e 100644 --- a/tests/bugs/gh_7062_test.py +++ b/tests/bugs/gh_7062_test.py @@ -6,6 +6,10 @@ TITLE: Creation of expression index does not release its statement correctly DESCRIPTION: FBTEST: bugs.gh_7062 +NOTES: + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -36,15 +40,17 @@ act = isql_act('db', test_script) -expected_stderr = """ - Statement failed, SQLSTATE = 22012 - Expression evaluation error for index "***unknown***" on table "TEST_A" - -arithmetic exception, numeric overflow, or string truncation - -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. -""" - @pytest.mark.version('>=4.0.1') def test_1(act: Action): - act.expected_stderr = expected_stderr - act.execute() - assert act.clean_stderr == act.clean_expected_stderr + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + expected_stdout = f""" + Statement failed, SQLSTATE = 22012 + Expression evaluation error for index "***unknown***" on table {SQL_SCHEMA_PREFIX}"TEST_A" + -arithmetic exception, numeric overflow, or string truncation + -Integer divide by zero. The code attempted to divide an integer value by an integer divisor of zero. + """ + + act.expected_stdout = expected_stdout + act.execute(combine_output = True) + assert act.clean_stdout == act.clean_expected_stdout From 87f48a550e9ca65ff5667d42e2596d48182fbd23 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:27:19 +0300 Subject: [PATCH 1026/1064] Added/Updated tests\bugs\gh_7094_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7094_test.py | 76 ++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/tests/bugs/gh_7094_test.py b/tests/bugs/gh_7094_test.py index 2f1bfe32..164cba38 100644 --- a/tests/bugs/gh_7094_test.py +++ b/tests/bugs/gh_7094_test.py @@ -10,6 +10,11 @@ Confirmed problem on 5.0.0.425. Checked on 5.0.0.1163, 4.0.4.2978. Test fails on 3.0.12 with 'invalid collation attribute', thus min_version was set to 4.0.2. + + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.876; 5.0.3.1668. """ import pytest @@ -46,33 +51,56 @@ select t1.* from t1 where c1 > 'c' plan (t1 natural) order by c1, c2; """ -act = isql_act('db', test_script) - -expected_stdout = """ - PLAN SORT (T1 INDEX (T1_C1_C2_DESC)) - C1 d - C2 d - C1 e - C2 e - C1 f - C2 f - C1 ch - C2 ch - - PLAN SORT (T1 NATURAL) - C1 d - C2 d - C1 e - C2 e - C1 f - C2 f - C1 ch - C2 ch -""" +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.intl @pytest.mark.version('>=4.0.2') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN SORT (T1 INDEX (T1_C1_C2_DESC)) + C1 d + C2 d + C1 e + C2 e + C1 f + C2 f + C1 ch + C2 ch + + PLAN SORT (T1 NATURAL) + C1 d + C2 d + C1 e + C2 e + C1 f + C2 f + C1 ch + C2 ch + """ + + expected_stdout_6x = """ + PLAN SORT ("PUBLIC"."T1" INDEX ("PUBLIC"."T1_C1_C2_DESC")) + C1 d + C2 d + C1 e + C2 e + C1 f + C2 f + C1 ch + C2 ch + PLAN SORT ("PUBLIC"."T1" NATURAL) + C1 d + C2 d + C1 e + C2 e + C1 f + C2 f + C1 ch + C2 ch + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From ae6880c02ed474f0388fc57c9d21f9daab3a26cd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:30:36 +0300 Subject: [PATCH 1027/1064] Added/Updated tests\bugs\gh_7118_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7118_test.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/tests/bugs/gh_7118_test.py b/tests/bugs/gh_7118_test.py index 3088a9c3..01c0fa92 100644 --- a/tests/bugs/gh_7118_test.py +++ b/tests/bugs/gh_7118_test.py @@ -10,8 +10,12 @@ https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 (13.09.2022 19:17, "More complete solution for #3357 and #7118") One more test that attempts to verify this commit: bugs/gh_7398_test.py - Checked on 3.0.11.33665, 4.0.3.2904, 5.0.0.964 + + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -74,17 +78,23 @@ act = isql_act('db', test_script) -"" - -expected_stdout = """ - PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) - PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) - PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) - PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) -""" - @pytest.mark.version('>=3.0.9') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) + PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) + PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) + PLAN JOIN (T1 INDEX (T1_COL), T2 INDEX (RDB$PRIMARY2), T3 INDEX (RDB$PRIMARY3)) + """ + + expected_stdout_6x = """ + PLAN JOIN ("T1" INDEX ("PUBLIC"."T1_COL"), "T2" INDEX ("PUBLIC"."RDB$PRIMARY2"), "T3" INDEX ("PUBLIC"."RDB$PRIMARY3")) + PLAN JOIN ("T1" INDEX ("PUBLIC"."T1_COL"), "T2" INDEX ("PUBLIC"."RDB$PRIMARY2"), "T3" INDEX ("PUBLIC"."RDB$PRIMARY3")) + PLAN JOIN ("T1" INDEX ("PUBLIC"."T1_COL"), "T2" INDEX ("PUBLIC"."RDB$PRIMARY2"), "T3" INDEX ("PUBLIC"."RDB$PRIMARY3")) + PLAN JOIN ("T1" INDEX ("PUBLIC"."T1_COL"), "T2" INDEX ("PUBLIC"."RDB$PRIMARY2"), "T3" INDEX ("PUBLIC"."RDB$PRIMARY3")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1b5b677a31c8999d5fcedeb0074a1a11dccccc2c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:32:35 +0300 Subject: [PATCH 1028/1064] Added/Updated tests\bugs\gh_7123_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7123_test.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_7123_test.py b/tests/bugs/gh_7123_test.py index 9ca4163f..0d3f98d2 100644 --- a/tests/bugs/gh_7123_test.py +++ b/tests/bugs/gh_7123_test.py @@ -13,6 +13,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -33,17 +36,19 @@ db = db_factory(init = init_script) act = python_act('db', substitutions = [('^((?!SQLSTATE|ID1(A|B|C|D)|ID2(A|B|C|D)).)*$', '')] ) -expected_stdout = """ - CREATE TABLE TEST (ID1A INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT 111) NOT NULL, - ID1B INTEGER GENERATED ALWAYS AS IDENTITY (START WITH -222 INCREMENT 222) NOT NULL, - ID1C INTEGER GENERATED ALWAYS AS IDENTITY (START WITH -333) NOT NULL, - ID2A INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT 1111) NOT NULL, - ID2B INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH -2222 INCREMENT 2222) NOT NULL, - ID2C INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH -3333) NOT NULL); -""" @pytest.mark.version('>=4.0.2') def test_1(act: Action): - # meta = act.extract_meta() + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' + expected_stdout = f""" + CREATE TABLE {SQL_SCHEMA_PREFIX}TEST (ID1A INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT 111) NOT NULL, + ID1B INTEGER GENERATED ALWAYS AS IDENTITY (START WITH -222 INCREMENT 222) NOT NULL, + ID1C INTEGER GENERATED ALWAYS AS IDENTITY (START WITH -333) NOT NULL, + ID2A INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT 1111) NOT NULL, + ID2B INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH -2222 INCREMENT 2222) NOT NULL, + ID2C INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH -3333) NOT NULL); + """ + act.expected_stdout = expected_stdout act.isql(switches=['-x'], charset='utf8', combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From fdf1c1f7efe99b03922ce53bb0eaef67e2f3797a Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:34:51 +0300 Subject: [PATCH 1029/1064] Added/Updated tests\bugs\gh_7137_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7137_test.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/tests/bugs/gh_7137_test.py b/tests/bugs/gh_7137_test.py index 9d5747dd..a7cb03d4 100644 --- a/tests/bugs/gh_7137_test.py +++ b/tests/bugs/gh_7137_test.py @@ -6,8 +6,12 @@ TITLE: Optimizer regression: bad plan (HASH instead of JOIN) is chosen for some inner joins NOTES: [26.04.2022] pzotov - Confirmed bug (ineffective execution plan) on 3.0.9.33560 (09.02.2022). - Checked on 6.0.0.336, 5.0.1.1383, 4.0.5.3086, 3.0.10.33569 (24.02.2022) - all fine. + Confirmed bug (ineffective execution plan) on 3.0.9.33560 (09.02.2022). + Checked on 6.0.0.336, 5.0.1.1383, 4.0.5.3086, 3.0.10.33569 (24.02.2022) - all fine. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -88,7 +92,7 @@ def test_1(act: Action, capsys): with cur.prepare(q) as ps: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan .split('\n')]) ) - expected_stdout = """ + expected_stdout_5x = """ Select Expression ....-> Nested Loop Join (inner) ........-> Filter @@ -104,7 +108,24 @@ def test_1(act: Action, capsys): ................-> Bitmap ....................-> Index "TEST_C_FK" Range Scan (full match) """ - - act.expected_stdout = expected_stdout + + expected_stdout_6x = """ + Select Expression + ....-> Nested Loop Join (inner) + ........-> Filter + ............-> Table "PUBLIC"."TEST_B" as "B" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_B_PK" Unique Scan + ........-> Filter + ............-> Table "PUBLIC"."TEST_A" as "A" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_A_NAME" Range Scan (full match) + ........-> Filter + ............-> Table "PUBLIC"."TEST_C" as "C" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_C_FK" 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 From 7db99b77dcc8d8f32c448bdc4f515b247a8a9639 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:37:23 +0300 Subject: [PATCH 1030/1064] Added/Updated tests\bugs\gh_7164_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7164_test.py | 42 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/tests/bugs/gh_7164_test.py b/tests/bugs/gh_7164_test.py index f53fb10c..5f0303fe 100644 --- a/tests/bugs/gh_7164_test.py +++ b/tests/bugs/gh_7164_test.py @@ -7,14 +7,17 @@ DESCRIPTION: NOTES: [28.02.2023] pzotov - ::: NB ::: - Currently improvement relates only to the case when data sources have no appropriate indices. - Otherwise "old" way is used: server attempts to make nested loopss, but finally it checks - whether hash join will be cheaper. And, if yes, then it applies hash join, but it is applied - to each joined stream, so execution plan will look as "nested" (multi-way) hashes. - Thanks to dimitr for explanation (letter 28.02.2023 10:52). - - Checked on 5.0.0.961 - all OK. + ::: NB ::: + Currently improvement relates only to the case when data sources have no appropriate indices. + Otherwise "old" way is used: server attempts to make nested loopss, but finally it checks + whether hash join will be cheaper. And, if yes, then it applies hash join, but it is applied + to each joined stream, so execution plan will look as "nested" (multi-way) hashes. + Thanks to dimitr for explanation (letter 28.02.2023 10:52). + Checked on 5.0.0.961 - all OK. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest @@ -23,12 +26,6 @@ db = db_factory() act = python_act('db') -expected_stdout = """ - PLAN HASH (T1 NATURAL, T2 NATURAL, T3 NATURAL) - PLAN HASH (A NATURAL, B NATURAL, C NATURAL) - PLAN HASH (HASH (V1 A NATURAL, V1 B NATURAL, V1 C NATURAL), HASH (V2 A NATURAL, V2 B NATURAL, V2 C NATURAL), HASH (V3 A NATURAL, V3 B NATURAL, V3 C NATURAL)) - PLAN HASH (HASH (U1 A NATURAL, U1 B NATURAL, U1 C NATURAL), HASH (U2 A NATURAL, U2 B NATURAL, U2 C NATURAL), HASH (U3 A NATURAL, U3 B NATURAL, U3 C NATURAL)) -""" @pytest.mark.version('>=5.0') def test_1(act: Action): test_sql = """ @@ -59,6 +56,21 @@ def test_1(act: Action): ; """ - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN HASH (T1 NATURAL, T2 NATURAL, T3 NATURAL) + PLAN HASH (A NATURAL, B NATURAL, C NATURAL) + PLAN HASH (HASH (V1 A NATURAL, V1 B NATURAL, V1 C NATURAL), HASH (V2 A NATURAL, V2 B NATURAL, V2 C NATURAL), HASH (V3 A NATURAL, V3 B NATURAL, V3 C NATURAL)) + PLAN HASH (HASH (U1 A NATURAL, U1 B NATURAL, U1 C NATURAL), HASH (U2 A NATURAL, U2 B NATURAL, U2 C NATURAL), HASH (U3 A NATURAL, U3 B NATURAL, U3 C NATURAL)) + """ + + expected_stdout_6x = """ + PLAN HASH ("T1" NATURAL, "T2" NATURAL, "T3" NATURAL) + PLAN HASH ("A" NATURAL, "B" NATURAL, "C" NATURAL) + PLAN HASH (HASH ("V1" "A" NATURAL, "V1" "B" NATURAL, "V1" "C" NATURAL), HASH ("V2" "A" NATURAL, "V2" "B" NATURAL, "V2" "C" NATURAL), HASH ("V3" "A" NATURAL, "V3" "B" NATURAL, "V3" "C" NATURAL)) + PLAN HASH (HASH ("U1" "A" NATURAL, "U1" "B" NATURAL, "U1" "C" NATURAL), HASH ("U2" "A" NATURAL, "U2" "B" NATURAL, "U2" "C" NATURAL), HASH ("U3" "A" NATURAL, "U3" "B" NATURAL, "U3" "C" NATURAL)) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=['-q'], input = test_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1c076e97d8437800c4f551cdf3f0288c94fb31e6 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:39:19 +0300 Subject: [PATCH 1031/1064] Added/Updated tests\bugs\gh_7167_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7167_test.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/bugs/gh_7167_test.py b/tests/bugs/gh_7167_test.py index 4c50e11e..e364142d 100644 --- a/tests/bugs/gh_7167_test.py +++ b/tests/bugs/gh_7167_test.py @@ -7,11 +7,13 @@ DESCRIPTION: NOTES: [28.02.2023] pzotov - Confirmed bug on 4.0.1.2692 Windows and Linux. - NB: on Linux we have to write SQL script into file with encoding = cp1251 - and run it as script, otherwise issue not reproduced. - - Checked on Windows and Linux, builds 5.0.0.961, 4.0.3.2903 - all OK. + Confirmed bug on 4.0.1.2692 Windows and Linux. + NB: on Linux we have to write SQL script into file with encoding = cp1251 + and run it as script, otherwise issue not reproduced. + Checked on Windows and Linux, builds 5.0.0.961, 4.0.3.2903 - all OK. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -22,11 +24,7 @@ db = db_factory(charset = 'win1251') act = python_act('db', substitutions = [('After line \\d+ in file .*', '')]) tmp_sql = temp_file('tmp_gh_7167.tmp.sql') -expected_stdout = """ - Statement failed, SQLSTATE = 23000 - violation of PRIMARY or UNIQUE KEY constraint "уни" on table "абв" - -Problematic key value is ("аб" = 'аб', "вг" = 'аб', "де" = 'аб') -""" + @pytest.mark.version('>=4.0.2') def test_1(act: Action, tmp_sql: Path): test_sql = """ @@ -40,6 +38,14 @@ def test_1(act: Action, tmp_sql: Path): insert into "абв" values ('аб','аб','аб'); """ tmp_sql.write_bytes(test_sql.encode('cp1251')) + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + violation of PRIMARY or UNIQUE KEY constraint "уни" on table {SQL_SCHEMA_PREFIX}"абв" + -Problematic key value is ("аб" = 'аб', "вг" = 'аб', "де" = 'аб') + """ + act.expected_stdout = expected_stdout act.isql(switches=['-q'], charset = 'win1251', input_file = tmp_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From beb0c39a158722de2f979d1b1eb960a0f0fbf54d Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:45:00 +0300 Subject: [PATCH 1032/1064] Added/Updated tests\bugs\gh_7220_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7220_test.py | 75 +++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/tests/bugs/gh_7220_test.py b/tests/bugs/gh_7220_test.py index d94e2f3c..be677667 100644 --- a/tests/bugs/gh_7220_test.py +++ b/tests/bugs/gh_7220_test.py @@ -7,8 +7,12 @@ DESCRIPTION: NOTES: [23.02.2023] pzotov - Confirmed bug on 5.0.0.520 (but 'drop table' will not fail only if it is executed in the same connect as DDL). - Checked on 5.0.0.958 - all fine. + Confirmed bug on 5.0.0.520 (but 'drop table' will not fail only if it is executed in the same connect as DDL). + Checked on 5.0.0.958 - all fine. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest from firebird.qa import * @@ -53,34 +57,55 @@ drop domain domain1; """ -expected_out = """ - RDB$DEPENDENT_NAME PKG - RDB$DEPENDED_ON_NAME TABLE1 +@pytest.mark.version('>=5.0') +def test_1(act: Action): - RDB$DEPENDENT_NAME PKG - RDB$DEPENDED_ON_NAME DOMAIN1 + expected_stdout_5x = """ + RDB$DEPENDENT_NAME PKG + RDB$DEPENDED_ON_NAME TABLE1 - RDB$DEPENDENT_NAME WAIT_EVENT - RDB$DEPENDED_ON_NAME TABLE1 - Records affected: 3 + RDB$DEPENDENT_NAME PKG + RDB$DEPENDED_ON_NAME DOMAIN1 - drop table table1; - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -cannot delete - -COLUMN TABLE1.N - -there are 1 dependencies + RDB$DEPENDENT_NAME WAIT_EVENT + RDB$DEPENDED_ON_NAME TABLE1 + Records affected: 3 - drop domain domain1; - Statement failed, SQLSTATE = 42000 - unsuccessful metadata update - -DROP DOMAIN DOMAIN1 failed - -Domain DOMAIN1 is used in procedure PKG.PROC2 (parameter name I) and cannot be dropped -""" + drop table table1; + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN TABLE1.N + -there are 1 dependencies -@pytest.mark.version('>=5.0') -def test_1(act: Action): + drop domain domain1; + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP DOMAIN DOMAIN1 failed + -Domain DOMAIN1 is used in procedure PKG.PROC2 (parameter name I) and cannot be dropped + """ + + expected_stdout_6x = """ + RDB$DEPENDENT_NAME PKG + RDB$DEPENDED_ON_NAME TABLE1 + RDB$DEPENDENT_NAME PKG + RDB$DEPENDED_ON_NAME DOMAIN1 + RDB$DEPENDENT_NAME WAIT_EVENT + RDB$DEPENDED_ON_NAME TABLE1 + Records affected: 3 + drop table table1; + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -cannot delete + -COLUMN "PUBLIC"."TABLE1"."N" + -there are 1 dependencies + drop domain domain1; + Statement failed, SQLSTATE = 42000 + unsuccessful metadata update + -DROP DOMAIN "PUBLIC"."DOMAIN1" failed + -Domain "PUBLIC"."DOMAIN1" is used in procedure "PUBLIC"."PKG"."PROC2" (parameter name "I") and cannot be dropped + """ - act.expected_stdout = expected_out + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=['-q'], combine_output = True, input = test_sql) assert act.clean_stdout == act.clean_expected_stdout From 456140a8b8a28cfa6d870f28a0d5f163fecf0c6e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:48:18 +0300 Subject: [PATCH 1033/1064] Added/Updated tests\bugs\gh_7256_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7256_test.py | 52 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/tests/bugs/gh_7256_test.py b/tests/bugs/gh_7256_test.py index 7638980d..66a89061 100644 --- a/tests/bugs/gh_7256_test.py +++ b/tests/bugs/gh_7256_test.py @@ -4,8 +4,7 @@ ID: issue-7256 ISSUE: 7256 TITLE: Inconsistent conversion of non-TEXT blobs in BLOB_APPEND -NOTES: - [22.02.2023] pzotov +DESCRIPTION: 1. Test makes TWO subsequent connections: 1) to write blobs in the table using charset UTF8 2) to READ that table using charset NONE. @@ -19,21 +18,23 @@ 3. Statement 'select blob_append() from test' currently does not show literal. This is a bug and must/will be fixed. After that, test will be adjusted. - +NOTES: + [22.02.2023] pzotov Thanks to Vlad for suggestions. Discussed 20-21 feb 2023. Checked on 5.0.0.958. - - [03.03.2023] pzotov + [03.03.2023] pzotov Added 'set blob all' because result of blob_append(null, null) must be visible as literal ''. Added substitution for suppressing 'Nullable' flags in the SQLDA output: it is sufficient for this test to check only datatypes of result. Discussed with Vlad, letters 02-mar-2023 16:01 and 03-mar-2023 14:43. - - Checked on 5.0.0.967, 4.0.3.2904 (intermediate build 03-mar-2023 12:33) + Checked on 5.0.0.967, 4.0.3.2904 (intermediate build 03-mar-2023 12:33) [14.12.2023] pzotov Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -108,30 +109,33 @@ act = isql_act('db', test_script, substitutions = [('^((?!SQLSTATE|sqltype:|BLOB_RESULT).)*$', ''), ('BLOB Nullable', 'BLOB'), ('[ \t]+', ' ')]) -expected_stdout = """ - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 1 OCTETS - : name: BLOB_APPEND alias: BLOB_RESULT_1 +@pytest.mark.version('>=4.0.3') +def test_1(act: Action): - 01: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 - : name: BLOB_APPEND alias: BLOB_RESULT_2 + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 1 {SQL_SCHEMA_PREFIX}OCTETS + : name: BLOB_APPEND alias: BLOB_RESULT_1 - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 21 ISO8859_1 - : name: BLOB_APPEND alias: BLOB_RESULT_3A + 01: sqltype: 520 BLOB scale: 0 subtype: 0 len: 8 + : name: BLOB_APPEND alias: BLOB_RESULT_2 - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 UTF8 - : name: BLOB_APPEND alias: BLOB_RESULT_3B + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 21 {SQL_SCHEMA_PREFIX}ISO8859_1 + : name: BLOB_APPEND alias: BLOB_RESULT_3A - 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 ASCII - : name: BLOB_APPEND alias: BLOB_RESULT_4 + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 {SQL_SCHEMA_PREFIX}UTF8 + : name: BLOB_APPEND alias: BLOB_RESULT_3B - 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 - : name: BLOB_APPEND alias: BLOB_RESULT_5 + 01: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 2 {SQL_SCHEMA_PREFIX}ASCII + : name: BLOB_APPEND alias: BLOB_RESULT_4 - BLOB_RESULT_5 -""" + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 0 len: 8 + : name: BLOB_APPEND alias: BLOB_RESULT_5 + + BLOB_RESULT_5 + """ -@pytest.mark.version('>=4.0.3') -def test_1(act: Action): act.expected_stdout = expected_stdout act.execute(combine_output = True, charset = 'None' ) assert act.clean_stdout == act.clean_expected_stdout + \ No newline at end of file From 02f847b1d05d2158a1fb9889d846ff90715c4142 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:52:45 +0300 Subject: [PATCH 1034/1064] Added/Updated tests\bugs\gh_7257_misc_datatypes_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7257_misc_datatypes_test.py | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_7257_misc_datatypes_test.py b/tests/bugs/gh_7257_misc_datatypes_test.py index 112dbce2..235e8a8c 100644 --- a/tests/bugs/gh_7257_misc_datatypes_test.py +++ b/tests/bugs/gh_7257_misc_datatypes_test.py @@ -8,13 +8,16 @@ Additional test to check misc datatypes in partial indices. NOTES: [18.01.2025] pzotov - Resultset of cursor that executes using instance of selectable PreparedStatement must be stored - in some variable in order to have ability close it EXPLICITLY (before PS will be freed). - Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). - This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 - The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). - - Checked on 6.0.0.409, 5.0.1.1469 + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). + Checked on 6.0.0.409, 5.0.1.1469 + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest @@ -113,7 +116,7 @@ def run_ddl_dml(act, capsys, dtype, v_chk, v_max, use_rand = True): if ps: ps.free() - act.expected_stdout = f""" + expected_stdout_5x = f""" Select Expression ....-> Aggregate ........-> Filter @@ -129,6 +132,25 @@ def run_ddl_dml(act, capsys, dtype, v_chk, v_max, use_rand = True): ....................-> Index "{idx_common_name}" Range Scan (full match) COUNT : 10 """ + + expected_stdout_6x = f""" + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "PUBLIC"."TEST" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."{idx_partial_name}" Full Scan + COUNT : 10 + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table "PUBLIC"."TEST" Access By ID + ................-> Bitmap + ....................-> Index "PUBLIC"."{idx_common_name}" Range Scan (full match) + COUNT : 10 + """ + + 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 act.reset() From 2f95b3b73e97c8dfe1c9c03816d0df8664a52310 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:55:57 +0300 Subject: [PATCH 1035/1064] Added/Updated tests\bugs\gh_7257_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7257_test.py | 94 ++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/tests/bugs/gh_7257_test.py b/tests/bugs/gh_7257_test.py index 11b110d4..9443cab9 100644 --- a/tests/bugs/gh_7257_test.py +++ b/tests/bugs/gh_7257_test.py @@ -5,11 +5,16 @@ ISSUE: 7257 TITLE: Support for partial indices NOTES: - Initial discussion: https://github.com/FirebirdSQL/firebird/issues/3750 - Checked on 5.0.0.957 (intermediate build). - NB. Currently this test contains only trivial cases for check. - More complex examples, including misc datatypes (non-ascii, decfloat and int128), - will be added later. + [18.01.2025] pzotov + Initial discussion: https://github.com/FirebirdSQL/firebird/issues/3750 + Checked on 5.0.0.957 (intermediate build). + NB. Currently this test contains only trivial cases for check. + More complex examples, including misc datatypes (non-ascii, decfloat and int128), + will be added later. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest @@ -102,37 +107,58 @@ """ -act = isql_act('db', test_script) - -expected_stdout = """ - PLAN (TEST NATURAL) - COUNT 4 - - PLAN (TEST NATURAL) - COUNT 3 - - PLAN (TEST INDEX (TEST_F01)) - COUNT 196 - - PLAN (TEST INDEX (TEST_F02)) - COUNT 195 - - - PLAN (TEST ORDER TEST_COMPUTED_ASC) - COUNT 190 - - PLAN (TEST ORDER TEST_COMPUTED_DEC) - COUNT 190 - - PLAN (TEST INDEX (TEST_COMPUTED_ASC)) - COUNT 190 - - PLAN (TEST INDEX (TEST_COMPUTED_DEC)) - COUNT 190 -""" +substitutions = [('[ \t]+', ' ')] +act = isql_act('db', test_script, substitutions = substitutions) @pytest.mark.version('>=5.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN (TEST NATURAL) + COUNT 4 + + PLAN (TEST NATURAL) + COUNT 3 + + PLAN (TEST INDEX (TEST_F01)) + COUNT 196 + + PLAN (TEST INDEX (TEST_F02)) + COUNT 195 + + + PLAN (TEST ORDER TEST_COMPUTED_ASC) + COUNT 190 + + PLAN (TEST ORDER TEST_COMPUTED_DEC) + COUNT 190 + + PLAN (TEST INDEX (TEST_COMPUTED_ASC)) + COUNT 190 + + PLAN (TEST INDEX (TEST_COMPUTED_DEC)) + COUNT 190 + """ + + expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" NATURAL) + COUNT 4 + PLAN ("PUBLIC"."TEST" NATURAL) + COUNT 3 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F01")) + COUNT 196 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_F02")) + COUNT 195 + PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_COMPUTED_ASC") + COUNT 190 + PLAN ("PUBLIC"."TEST" ORDER "PUBLIC"."TEST_COMPUTED_DEC") + COUNT 190 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_COMPUTED_ASC")) + COUNT 190 + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_COMPUTED_DEC")) + COUNT 190 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 1d837366fffc73c0e0dc5253b9a2ef5a460af5ab Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Fri, 4 Jul 2025 23:58:10 +0300 Subject: [PATCH 1036/1064] Added/Updated tests\bugs\gh_7269_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7269_test.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_7269_test.py b/tests/bugs/gh_7269_test.py index a19440ad..c1aee6b0 100644 --- a/tests/bugs/gh_7269_test.py +++ b/tests/bugs/gh_7269_test.py @@ -12,7 +12,11 @@ gbak:adjusting the ONLINE and FORCED WRITES flags NOTES: [02.11.2024] pzotov - Checked on 5.0.2.1551, 6.0.0.415. + Checked on 5.0.2.1551, 6.0.0.415. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import subprocess from pathlib import Path @@ -47,7 +51,7 @@ def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): if act.match_any(line.strip(), allowed_patterns): print(line) - expected_stdout = """ + expected_stdout_5x = """ gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A3" on table "A3" gbak: ERROR: Problematic key value is ("ID" = 9) gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A1" on table "A1" @@ -63,6 +67,22 @@ def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): gbak: ERROR: Run gfix -online to bring database online without active indices. """ - act.expected_stdout = expected_stdout + expected_stdout_6x = """ + gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A3" on table "PUBLIC"."A3" + gbak: ERROR: Problematic key value is ("ID" = 9) + gbak: ERROR:violation of PRIMARY or UNIQUE KEY constraint "PK_A1" on table "PUBLIC"."A1" + gbak: ERROR: Problematic key value is ("ID" = 5) + gbak: ERROR:Cannot create foreign key constraint "FK_A1". Partner index does not exist or is inactive. + gbak: ERROR:violation of FOREIGN KEY constraint "FK_A2" on table "PUBLIC"."B2" + gbak: ERROR: Foreign key reference target does not exist + gbak: ERROR: Problematic key value is ("A2_ID" = 5) + gbak: ERROR:Cannot create foreign key constraint "FK_A3". Partner index does not exist or is inactive. + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + gbak: ERROR:Database is not online due to failure to activate one or more indices. + gbak: ERROR: Run gfix -online to bring database online without active indices. + """ + + 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 From be8f9c32892631f5a20681f7e0d1244423f6ba81 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:19:24 +0300 Subject: [PATCH 1037/1064] Added/Updated tests\bugs\gh_7331_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7331_test.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/bugs/gh_7331_test.py b/tests/bugs/gh_7331_test.py index 55dd971e..b3e325d0 100644 --- a/tests/bugs/gh_7331_test.py +++ b/tests/bugs/gh_7331_test.py @@ -6,13 +6,16 @@ TITLE: Cost-based choice between nested loop join and hash join NOTES: [20.02.2023] pzotov - Confirmed difference between snapshots before and after commit - https://github.com/FirebirdSQL/firebird/commit/99c9f63f874d74beb53d338c97c033fe7c8d71a9 - Checked on 5.0.0.763 (plan did not use hash join); 5.0.0.957 (plan uses HJ). - + Confirmed difference between snapshots before and after commit + https://github.com/FirebirdSQL/firebird/commit/99c9f63f874d74beb53d338c97c033fe7c8d71a9 + Checked on 5.0.0.763 (plan did not use hash join); 5.0.0.957 (plan uses HJ). [12.09.2023] pzotov - Adjusted plan for query #2 after letter from dimitr, 11-sep-2023 20:23. - Checked on 5.0.0.1204 + Adjusted plan for query #2 after letter from dimitr, 11-sep-2023 20:23. + Checked on 5.0.0.1204 + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest @@ -112,13 +115,19 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN HASH (LINEITEM INDEX (LINEITEM_SHIPDATE), ORDERS NATURAL) - PLAN HASH (JOIN (CUSTOMER NATURAL, ORDERS INDEX (ORDERS_CUSTKEY_FK)), LINEITEM INDEX (LINEITEM_SHIPDATE)) -""" - @pytest.mark.version('>=5.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN HASH (LINEITEM INDEX (LINEITEM_SHIPDATE), ORDERS NATURAL) + PLAN HASH (JOIN (CUSTOMER NATURAL, ORDERS INDEX (ORDERS_CUSTKEY_FK)), LINEITEM INDEX (LINEITEM_SHIPDATE)) + """ + + expected_stdout_6x = """ + PLAN HASH ("PUBLIC"."LINEITEM" INDEX ("PUBLIC"."LINEITEM_SHIPDATE"), "PUBLIC"."ORDERS" NATURAL) + PLAN HASH (JOIN ("PUBLIC"."CUSTOMER" NATURAL, "PUBLIC"."ORDERS" INDEX ("PUBLIC"."ORDERS_CUSTKEY_FK")), "PUBLIC"."LINEITEM" INDEX ("PUBLIC"."LINEITEM_SHIPDATE")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 9080af5fbd735e940b97966857b1148ef37c4fdf Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:31:34 +0300 Subject: [PATCH 1038/1064] Added/Updated tests\bugs\gh_7350_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7350_test.py | 841 ++++++++++++++++++------------------- 1 file changed, 420 insertions(+), 421 deletions(-) diff --git a/tests/bugs/gh_7350_test.py b/tests/bugs/gh_7350_test.py index e4b6158b..6930858e 100644 --- a/tests/bugs/gh_7350_test.py +++ b/tests/bugs/gh_7350_test.py @@ -13,29 +13,22 @@ All kinds of transaction isolation levels are involved: TABLE STABILITY; SNAPSHOT; RC READ_CONSISTENCY; RC REC_VER and RC NO_REC_VER. NOTES: [22.11.2023] pzotov - 1. Parameter ReadConsistency in firebird.conf must be set to 0, i.e. NOT-default value. - 2. TIL = "RC NO_record_version" can be used to check feature since gh-7811 was fixed (20.11.2023 in master) - 3. Only persistent table is checked. For session-level GTT (using two transactions for single attach) - it is unable to run 'select ... with lock' or 'update/delete ... skip locked': exception raises with message - "SQLSTATE = HY000 / Cannot select temporary table ... WITH LOCK" - Discussed with dimitr and hvlad, 13.09.2023 - 4. Added WAIT mode to be checked after fixed https://github.com/FirebirdSQL/firebird/issues/7700 - ( https://github.com/FirebirdSQL/firebird/commit/5b14baa37b6ee214cd8ccc21f2e99dce119fe60e ) - NOTE: before fix gh-7700, following statement hanged: - set transaction read committed record_version WAIT; - select id from test order by id with lock skip locked - 5. Here we check only 'SELECT ... WITH LOCK' behavour. Results of UPDATE and DELETE are checked in gh_7810_test.py - - [25.11.2023] pzotov - Writing code requires more care since 6.0.0.150: ISQL does not allow to specify THE SAME terminator twice, - i.e. - set term @; select 1 from rdb$database @ set term @; - will not compile ("Unexpected end of command" raises). - - Checked on 6.0.0.137 (SS/CS), 5.0.0.1274 (SS/CS). - - [27.11.2023] pzotov - Removed branched for 5.x vs 6.x, code now the same for 5.x and 6.x - Checked on 5.0.0.1280 (intermediate build 27.11.2023, after backporting, commit dc2d85c17b41fb6c378bffc0896338c4f8856998). + 1. Parameter ReadConsistency in firebird.conf must be set to 0, i.e. NOT-default value. + 2. TIL = "RC NO_record_version" can be used to check feature since gh-7811 was fixed (20.11.2023 in master) + 3. Only persistent table is checked. For session-level GTT (using two transactions for single attach) + it is unable to run 'select ... with lock' or 'update/delete ... skip locked': exception raises with message + "SQLSTATE = HY000 / Cannot select temporary table ... WITH LOCK" + Discussed with dimitr and hvlad, 13.09.2023 + 4. Added WAIT mode to be checked after fixed https://github.com/FirebirdSQL/firebird/issues/7700 + ( https://github.com/FirebirdSQL/firebird/commit/5b14baa37b6ee214cd8ccc21f2e99dce119fe60e ) + NOTE: before fix gh-7700, following statement hanged: + set transaction read committed record_version WAIT; + select id from test order by id with lock skip locked + 5. Here we check only 'SELECT ... WITH LOCK' behavour. Results of UPDATE and DELETE are checked in gh_7810_test.py + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863; 5.0.3.1668. """ import pytest @@ -44,410 +37,16 @@ import time db = db_factory() -substitutions = [ ('transaction number is \\d+', 'transaction number is'), - ("-At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' line.*", "-At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL'"), - ("-At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' line.*", "-At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE'"), +substitutions = [ (r'line(:)?\s+\d+.*', ''), + ('transaction number is \\d+', 'transaction number is'), + #("-At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' line.*", "-At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL'"), + #("-At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' line.*", "-At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE'"), ('Data source : Firebird::localhost:.*', 'Data source : Firebird::localhost:') ] act = python_act('db', substitutions = substitutions) CHECK_SQL = 'select id from test order by id with lock skip locked' -expected_stdout = f""" - QUERY_TYPE = DSQL, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: - lock conflict on no wait transaction - -Acquire lock for relation (TEST) failed - -901 - 335544345 - 335544382 - QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -817 - 335544361 - QUERY_TYPE = DSQL, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: - lock conflict on no wait transaction - -Acquire lock for relation (TEST) failed - -901 - 335544345 - 335544382 - QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: - lock conflict on no wait transaction - -Acquire lock for relation (TEST) failed - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -901 - 335544345 - 335544382 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - attempted update during read-only transaction - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -817 - 335544361 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: - lock conflict on no wait transaction - -Acquire lock for relation (TEST) failed - -At procedure 'SP_GET_UNLOCKED_ROWS_LOCAL' - -901 - 335544345 - 335544382 - 335544842 - QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544345 : lock conflict on no wait transaction - 335544382 : Acquire lock for relation (TEST) failed - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: - Execute statement error at isc_dsql_fetch : - 335544361 : attempted update during read-only transaction - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: - Execute statement error at isc_dsql_fetch : - 335544345 : lock conflict on no wait transaction - 335544382 : Acquire lock for relation (TEST) failed - Statement : select id from test order by id with lock skip locked - Data source : Firebird::localhost: - -At procedure 'SP_GET_UNLOCKED_ROWS_REMOTE' - -901 - 335544926 - 335544842 - QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 - QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: - ID=2 - ID=3 - ID=4 - ID=6 - ID=7 - ID=8 - ID=10 -""" - @pytest.mark.es_eds @pytest.mark.version('>=5.0') def test_1(act: Action, capsys): @@ -539,6 +138,406 @@ def test_1(act: Action, capsys): finally: tx_free_seeker.rollback() + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_TEST_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' + SP_LOCAL_NAME = "'SP_GET_UNLOCKED_ROWS_LOCAL'" if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"SP_GET_UNLOCKED_ROWS_LOCAL"' + SP_REMOTE_NAME = "'SP_GET_UNLOCKED_ROWS_REMOTE'" if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"SP_GET_UNLOCKED_ROWS_REMOTE"' + + expected_stdout = f""" + QUERY_TYPE = DSQL, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: + lock conflict on no wait transaction + -Acquire lock for relation ({TABLE_TEST_NAME}) failed + -901 + 335544345 + 335544382 + QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -817 + 335544361 + QUERY_TYPE = DSQL, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: + lock conflict on no wait transaction + -Acquire lock for relation ({TABLE_TEST_NAME}) failed + -901 + 335544345 + 335544382 + QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = DSQL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: + lock conflict on no wait transaction + -Acquire lock for relation ({TABLE_TEST_NAME}) failed + -At procedure {SP_LOCAL_NAME} + -901 + 335544345 + 335544382 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + attempted update during read-only transaction + -At procedure {SP_LOCAL_NAME} + -817 + 335544361 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: + lock conflict on no wait transaction + -Acquire lock for relation ({TABLE_TEST_NAME}) failed + -At procedure {SP_LOCAL_NAME} + -901 + 335544345 + 335544382 + 335544842 + QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_LOCAL, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = SERIALIZABLE, ACCESS = READ, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544345 : lock conflict on no wait transaction + 335544382 : Acquire lock for relation ({TABLE_TEST_NAME}) failed + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = READ, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = READ, WAIT = WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = READ, WAIT = WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = READ, WAIT = WAIT: + Execute statement error at isc_dsql_fetch : + 335544361 : attempted update during read-only transaction + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = SERIALIZABLE, ACCESS = WRITE, WAIT = NO_WAIT: + Execute statement error at isc_dsql_fetch : + 335544345 : lock conflict on no wait transaction + 335544382 : Acquire lock for relation ({TABLE_TEST_NAME}) failed + Statement : select id from test order by id with lock skip locked + Data source : Firebird::localhost: + -At procedure {SP_REMOTE_NAME} + -901 + 335544926 + 335544842 + QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = SNAPSHOT, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_READ_CONSISTENCY, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = NO_WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + QUERY_TYPE = PSQL_REMOTE, TIL = READ_COMMITTED_NO_RECORD_VERSION, ACCESS = WRITE, WAIT = WAIT: + ID=2 + ID=3 + ID=4 + ID=6 + ID=7 + ID=8 + ID=10 + """ + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 40dd1e39b46f9b88e262064172f1e5974db90ff3 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:33:30 +0300 Subject: [PATCH 1039/1064] Added/Updated tests\bugs\gh_7350_test.py: correction in comments --- tests/bugs/gh_7350_test.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_7350_test.py b/tests/bugs/gh_7350_test.py index 6930858e..d09b126b 100644 --- a/tests/bugs/gh_7350_test.py +++ b/tests/bugs/gh_7350_test.py @@ -25,10 +25,9 @@ set transaction read committed record_version WAIT; select id from test order by id with lock skip locked 5. Here we check only 'SELECT ... WITH LOCK' behavour. Results of UPDATE and DELETE are checked in gh_7810_test.py - [04.07.2025] pzotov - Separated expected output for FB major versions prior/since 6.x. - No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. - Checked on 6.0.0.863; 5.0.3.1668. + [05.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest From b1896f44f1da284a0c8c3ffe5e0de2bd8c9b6fe2 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:34:45 +0300 Subject: [PATCH 1040/1064] Updated tests\bugs\gh_7398_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_7398_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_7398_test.py b/tests/bugs/gh_7398_test.py index 830480ce..9d9e4dc5 100644 --- a/tests/bugs/gh_7398_test.py +++ b/tests/bugs/gh_7398_test.py @@ -115,20 +115,20 @@ def replace_leading(source, char="."): ................-> Hash Join (inner) (keys: 1, total key length: 4) ....................-> Nested Loop Join (inner) ........................-> Filter - ............................-> Table "PCP_TIN_REC" as "R" Full Scan + ............................-> Table "PUBLIC"."PCP_TIN_REC" as "R" Full Scan ........................-> Filter - ............................-> Table "PCP_TIN_REC_MAT" as "M" Access By ID + ............................-> Table "PUBLIC"."PCP_TIN_REC_MAT" as "M" Access By ID ................................-> Bitmap - ....................................-> Index "FK_PCP_TIN_REC_MAT_REC" Range Scan (full match) + ....................................-> Index "PUBLIC"."FK_PCP_TIN_REC_MAT_REC" Range Scan (full match) ........................-> Filter - ............................-> Table "INV_ETQ_MAT" as "CUS" Access By ID + ............................-> Table "PUBLIC"."INV_ETQ_MAT" as "CUS" Access By ID ................................-> Bitmap - ....................................-> Index "IDX_INV_ETQ_MAT_ANOMES" Range Scan (full match) + ....................................-> Index "PUBLIC"."IDX_INV_ETQ_MAT_ANOMES" Range Scan (full match) ....................-> Record Buffer (record length: 33) ........................-> Filter - ............................-> Table "INV_ETQ_NAT" as "NAT" Access By ID + ............................-> Table "PUBLIC"."INV_ETQ_NAT" as "NAT" Access By ID ................................-> Bitmap - ....................................-> Index "IDX_INV_ETQ_NAT_CML_STAT" Range Scan (full match) + ....................................-> Index "PUBLIC"."IDX_INV_ETQ_NAT_CML_STAT" Range Scan (full match) """ @pytest.mark.version('>=4.0') From a421f66e26d27a442a40862323f0f95c54648770 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:38:01 +0300 Subject: [PATCH 1041/1064] Added/Updated tests\bugs\gh_7413_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7413_test.py | 40 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/tests/bugs/gh_7413_test.py b/tests/bugs/gh_7413_test.py index 994f21f9..b18b924a 100644 --- a/tests/bugs/gh_7413_test.py +++ b/tests/bugs/gh_7413_test.py @@ -6,8 +6,12 @@ TITLE: Regression: bad plan in FB 3.0.9+ (correct in FB 3.0.8) NOTES: [01.03.2023] pzotov - Test database was created beforehand, fulfilled with data provided in the ticket, backed up and compressed. - Checked on 3.0.11.33665, 4.0.3.2904, 5.0.0.964 + Test database was created beforehand, fulfilled with data provided in the ticket, backed up and compressed. + Checked on 3.0.11.33665, 4.0.3.2904, 5.0.0.964 + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -18,16 +22,8 @@ db = db_factory() -act = python_act('db') - -expected_stdout = """ - PLAN JOIN (T3 INDEX (XAK2T3), T1 INDEX (R_542), T2 INDEX (XPKT2)) - ID_X 1 - ID_T1 6026229 - TOTAL 30.0000 - INVOICE_NO 1683998 - CREATED_AT 2022-11-28 -""" +substitutions = [('[ \t]+', ' ')] +act = python_act('db', substitutions = substitutions) fbk_file = temp_file('gh_7413.tmp.fbk') @@ -54,7 +50,25 @@ def test_1(act: Action, fbk_file: Path, capsys): where t3.invoice_no = 1683998; """ - act.expected_stdout = expected_stdout + expected_stdout_5x = """ + PLAN JOIN (T3 INDEX (XAK2T3), T1 INDEX (R_542), T2 INDEX (XPKT2)) + ID_X 1 + ID_T1 6026229 + TOTAL 30.0000 + INVOICE_NO 1683998 + CREATED_AT 2022-11-28 + """ + + expected_stdout_6x = """ + PLAN JOIN ("PUBLIC"."T3" INDEX ("PUBLIC"."XAK2T3"), "PUBLIC"."T1" INDEX ("PUBLIC"."R_542"), "PUBLIC"."T2" INDEX ("PUBLIC"."XPKT2")) + ID_X 1 + ID_T1 6026229 + TOTAL 30.0000 + INVOICE_NO 1683998 + CREATED_AT 2022-11-28 + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.isql(switches=[], input = script, combine_output=True) assert act.clean_stdout == act.clean_expected_stdout From 1e714c5156bd330ce0897a03fd605a4eddb01c1f Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:48:30 +0300 Subject: [PATCH 1042/1064] Added/Updated tests\bugs\gh_7426_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7426_test.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/bugs/gh_7426_test.py b/tests/bugs/gh_7426_test.py index c4338dbe..f4a9d0ae 100644 --- a/tests/bugs/gh_7426_test.py +++ b/tests/bugs/gh_7426_test.py @@ -17,12 +17,15 @@ No errors must present in the trace log. NOTES: [07-sep-2023] pzotov - ::: NB ::: - 1. It must be noted that the term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action - occurs when unit code is loaded into metadata cache. - 2. Currently there is no way to specify in the trace what EXACT type of DDL trigger fired. It is shown as "AFTER DDL". - - Checked on 5.0.0.1190. + 1. The term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action + occurs when unit code is loaded into metadata cache. + 2. Currently there is no way to specify in the trace what EXACT type of DDL trigger fired. + It is shown as "AFTER DDL". + Checked on 5.0.0.1190. + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668. """ import locale import re @@ -38,7 +41,7 @@ 'log_trigger_compile = true', ] -allowed_patterns = [ ' ERROR AT ', 'Trigger TRG_ANY_DDL_STATEMENT_', ] +allowed_patterns = [ ' ERROR AT ', 'Trigger ("PUBLIC".)?(")?TRG_ANY_DDL_STATEMENT_(BEFORE|AFTER)(")?', ] allowed_patterns = [ re.compile(r, re.IGNORECASE) for r in allowed_patterns] @pytest.mark.trace @@ -64,7 +67,7 @@ def test_1(act: Action, capsys): rdb$set_context('USER_SESSION', 'SKIP_DDL_TRG', '1'); end ^ - create or alter trigger trg_any_ddl_statement_alter active after any ddl statement as + create or alter trigger trg_any_ddl_statement_after active after any ddl statement as begin if (rdb$get_context('USER_SESSION', 'SKIP_DDL_TRG') is null) then execute statement @@ -135,11 +138,16 @@ def test_1(act: Action, capsys): if p.search(line): print(line.strip()) - expected_stdout = f""" + expected_stdout_5x = f""" Trigger TRG_ANY_DDL_STATEMENT_BEFORE (BEFORE DDL): - Trigger TRG_ANY_DDL_STATEMENT_ALTER (AFTER DDL): + Trigger TRG_ANY_DDL_STATEMENT_AFTER (AFTER DDL): """ - act.expected_stdout = expected_stdout + expected_stdout_6x = f""" + Trigger "PUBLIC"."TRG_ANY_DDL_STATEMENT_BEFORE" (BEFORE DDL): + Trigger "PUBLIC"."TRG_ANY_DDL_STATEMENT_AFTER" (AFTER DDL): + """ + + 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 From 4a227084c59c4e3290265952b006876a4b6280f8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:51:45 +0300 Subject: [PATCH 1043/1064] Added/Updated tests\bugs\gh_7461_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7461_test.py | 61 ++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/tests/bugs/gh_7461_test.py b/tests/bugs/gh_7461_test.py index 8aea90a8..c3de3e85 100644 --- a/tests/bugs/gh_7461_test.py +++ b/tests/bugs/gh_7461_test.py @@ -6,36 +6,33 @@ TITLE: Differences in field metadata descriptions between Firebird 2.5 and Firebird 4 NOTES: [21.01.2024] pzotov + NB: original title of ticket was changed. Commits refer to pull reuest rather than to this ticket number: + FB 4.x (16.11.2023): https://github.com/FirebirdSQL/firebird/commit/2886cd78991209842ee7e3065bde83ab75571af4 + FB 5.x (17.11.2023): https://github.com/FirebirdSQL/firebird/commit/1ed7f81f168b643a29357fce2e1f49156e9f5a1f + FB 6.x (17.11.2023): https://github.com/FirebirdSQL/firebird/commit/ab6aced05723dc1b2e6bb96bfdaa86cb3090daf2 + Before fix: + 01: sqltype: 580 INT64 Nullable scale: -2 subtype: 1 len: 8 + : name: alias: SALARY --- + : table: owner: + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: alias: EMP_NO --- + : table: owner: --- - NB: original title of ticket was changed. Commits refer to pull reuest rather than to this ticket number: - FB 4.x (16.11.2023): https://github.com/FirebirdSQL/firebird/commit/2886cd78991209842ee7e3065bde83ab75571af4 - FB 5.x (17.11.2023): https://github.com/FirebirdSQL/firebird/commit/1ed7f81f168b643a29357fce2e1f49156e9f5a1f - FB 6.x (17.11.2023): https://github.com/FirebirdSQL/firebird/commit/ab6aced05723dc1b2e6bb96bfdaa86cb3090daf2 - Actual text of commits: - FB 4.x: - Merge pull request #7848 from medi6/4.0.2 - Differencies in queries results between Firebird 2.5 and Firebird 4 - FB 5.x and 6.x: - correction metaData + After fix: + 01: sqltype: 580 INT64 Nullable scale: -2 subtype: 1 len: 8 + : name: MAX alias: SALARY +++ + : table: owner: + 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: EMP_NO alias: EMP_NO +++ + : table: SALARY_HISTORY owner: SYSDBA +++ - Before fix: - 01: sqltype: 580 INT64 Nullable scale: -2 subtype: 1 len: 8 - : name: alias: SALARY --- - : table: owner: - 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: alias: EMP_NO --- - : table: owner: --- + Confirmed bug on 4.0.4.3016, 5.0.0.1268 + Checked on 4.0.4.3021 (build date: 17-nov-2023), 5.0.0.1271 (build date: 18-nov-2023); 6.0.0.219 - After fix: - 01: sqltype: 580 INT64 Nullable scale: -2 subtype: 1 len: 8 - : name: MAX alias: SALARY +++ - : table: owner: - 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: EMP_NO alias: EMP_NO +++ - : table: SALARY_HISTORY owner: SYSDBA +++ - - Confirmed bug on 4.0.4.3016, 5.0.0.1268 - Checked on 4.0.4.3021 (build date: 17-nov-2023), 5.0.0.1271 (build date: 18-nov-2023); 6.0.0.219 + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -66,13 +63,19 @@ @pytest.mark.version('>=4.0.5') def test_1(act: Action): - expected_stdout = f""" + expected_stdout_5x = f""" : name: MAX alias: SALARY : table: owner: : name: EMP_NO alias: EMP_NO : table: SALARY_HISTORY owner: {act.db.user} """ + expected_stdout_6x = f""" + : name: MAX alias: SALARY + : table: schema: owner: + : name: EMP_NO alias: EMP_NO + : table: SALARY_HISTORY schema: PUBLIC owner: SYSDBA + """ - act.expected_stdout = expected_stdout + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From b07452781f26758d13e787fdd301c62012798016 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 17:56:41 +0300 Subject: [PATCH 1044/1064] Added/Updated tests\bugs\gh_7466_plans_tracking_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7466_plans_tracking_test.py | 161 +++++++++++++++++----- 1 file changed, 125 insertions(+), 36 deletions(-) diff --git a/tests/bugs/gh_7466_plans_tracking_test.py b/tests/bugs/gh_7466_plans_tracking_test.py index b9913aa9..b59283f8 100644 --- a/tests/bugs/gh_7466_plans_tracking_test.py +++ b/tests/bugs/gh_7466_plans_tracking_test.py @@ -11,44 +11,44 @@ We check here that compiling of this SP leads to appearing in the trace execution plans for every statement. NOTES: [18-aug-2023] pzotov - 1. It must be noted that the term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action - occurs when unit code is loaded into metadata cache. - 2. All subqueries like EXISTS() or IN() (and their "not" form) will be displayed in the trace as "separate" block - followed by block with "Select expression" or "Cursor". This seems not readable but currently it is so. - 3. Number of lines and columns for 'Subquery' will be shown only when this subquery is used as part PSQL statement - (i.e. not as part of SQL query) -- see 'decode()' below: - ======= - Sub-query (line 37, column 26) - -> Singularity Check - ... - ======= - 4. Plans, of course, can be changed in the future, so this test must be adjusted if this will occur. - - Thanks to dimitr for explanations. - Discussed with dimitr, letters 18.08.2023. - - Checked on 5.0.0.1164 + 1. It must be noted that the term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action + occurs when unit code is loaded into metadata cache. + 2. All subqueries like EXISTS() or IN() (and their "not" form) will be displayed in the trace as "separate" block + followed by block with "Select expression" or "Cursor". This seems not readable but currently it is so. + 3. Number of lines and columns for 'Subquery' will be shown only when this subquery is used as part PSQL statement + (i.e. not as part of SQL query) -- see 'decode()' below: + ======= + Sub-query (line 37, column 26) + -> Singularity Check + ... + ======= + 4. Plans, of course, can be changed in the future, so this test must be adjusted if this will occur. + + Thanks to dimitr for explanations. + Discussed with dimitr, letters 18.08.2023. + Checked on 5.0.0.1164 [08-sep-2023] pzotov - 1. Changed plan output: it is desirable to show indentations but they are 'swallowed' when act.clean_stdout is displayed. - Because of that, explained plan lines are 'padded' with dot character to their original length. - 2. Adjusted execution plan for one of queries to actual: one need to replace "Range Scan" with "List Scan" if we have - subquery with IN-list which refers to some columns from outer query. - See: https://github.com/FirebirdSQL/firebird/commit/5df6668c7bf5a4b27e15f687f8c6cc40e260ced8 - (Allow computable but non-invariant lists to be used for index lookup) - - Checked on 5.0.0.1200 - + 1. Changed plan output: it is desirable to show indentations but they are 'swallowed' when act.clean_stdout is displayed. + Because of that, explained plan lines are 'padded' with dot character to their original length. + 2. Adjusted execution plan for one of queries to actual: one need to replace "Range Scan" with "List Scan" if we have + subquery with IN-list which refers to some columns from outer query. + See: https://github.com/FirebirdSQL/firebird/commit/5df6668c7bf5a4b27e15f687f8c6cc40e260ced8 + (Allow computable but non-invariant lists to be used for index lookup) + Checked on 5.0.0.1200 [19-dec-2023] pzotov - Removed 'rand()' in order to have predictable values in table column. Use mod() instead. - Unstable outcomes started since 6.0.0.180 (18.12.2023). - It seems that following commits caused this: - https://github.com/FirebirdSQL/firebird/commit/ae427762d5a3e740b69c7239acb9e2383bc9ca83 // 5.x - https://github.com/FirebirdSQL/firebird/commit/f647dfd757de3c4065ef2b875c95d19311bb9691 // 6.x - + Removed 'rand()' in order to have predictable values in table column. Use mod() instead. + Unstable outcomes started since 6.0.0.180 (18.12.2023). + It seems that following commits caused this: + https://github.com/FirebirdSQL/firebird/commit/ae427762d5a3e740b69c7239acb9e2383bc9ca83 // 5.x + https://github.com/FirebirdSQL/firebird/commit/f647dfd757de3c4065ef2b875c95d19311bb9691 // 6.x [04-feb-2025] - Adjusted execution plan for EXISTS() part of recursive query: "List Scan" was replaced with "Range Scan" for - "and m0a.x in (dx.y, dx.z)". This change caused by commit 0cc77c89 ("Fix #8109: Plan/Performance regression ...") + Adjusted execution plan for EXISTS() part of recursive query: "List Scan" was replaced with "Range Scan" for + "and m0a.x in (dx.y, dx.z)". This change caused by commit 0cc77c89 ("Fix #8109: Plan/Performance regression ...") + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668. """ import locale import re @@ -194,7 +194,7 @@ def test_1(act: Action, capsys): if start_show and line.rstrip(): print( replace_leading(line,'.') ) - expected_stdout = f""" + expected_stdout_5x = """ Sub-query (invariant) ....-> Filter ........-> Aggregate @@ -283,6 +283,95 @@ def test_1(act: Action, capsys): ......0 ms """ - act.expected_stdout = expected_stdout + expected_stdout_6x = """ + Sub-query (invariant) + ....-> Filter + ........-> Aggregate + ............-> Table "PUBLIC"."TDETL" as "K" "DY" Access By ID + ................-> Index "PUBLIC"."TDETL_FK" Full Scan + Cursor "K"(line, column) + ....-> Filter (preliminary) + ........-> Nested Loop Join (inner) + ............-> Table "PUBLIC"."TMAIN" as "K" "M4" Full Scan + ............-> Filter + ................-> Table "PUBLIC"."TDETL" as "K" "D4" "DX" Access By ID + ....................-> Bitmap And + ........................-> Bitmap And + ............................-> Bitmap + ................................-> Index "PUBLIC"."TDETL_Z" Range Scan (lower bound: 1/1) + ............................-> Bitmap + ................................-> Index "PUBLIC"."TDETL_Y" Range Scan (upper bound: 1/1) + ........................-> Bitmap + ............................-> Index "PUBLIC"."TDETL_FK" Range Scan (full match) + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."TMAIN" as "M0" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TMAIN_X" Range Scan (lower bound: 1/1) + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."TMAIN" as "R" "M0A" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "PUBLIC"."TMAIN_X" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TMAIN_X" Range Scan (full match) + Select Expression(line, column) + ....-> Singularity Check + ........-> Aggregate + ............-> Filter + ................-> Recursion + ....................-> Filter + ........................-> Table "PUBLIC"."TDETL" as "R" "D0" Access By ID + ............................-> Bitmap + ................................-> Index "PUBLIC"."TDETL_FK" Range Scan (full match) + ....................-> Filter + ........................-> Table "PUBLIC"."TDETL" as "R" "DX" Access By ID + ............................-> Bitmap + ................................-> Index "PUBLIC"."TDETL_FK" Range Scan (full match) + Sub-query(line, column) + ....-> Singularity Check + ........-> Aggregate + ............-> Table "PUBLIC"."TMAIN" as "M1A" Full Scan + Sub-query(line, column) + ....-> Singularity Check + ........-> Aggregate + ............-> Table "PUBLIC"."TMAIN" as "M1B" Access By ID + ................-> Index "PUBLIC"."TMAIN_X" Full Scan + Sub-query(line, column) + ....-> Singularity Check + ........-> Aggregate + ............-> Table "PUBLIC"."TDETL" as "D1B" Access By ID + ................-> Index "PUBLIC"."TDETL_FK" Full Scan + Sub-query(line, column) + ....-> Singularity Check + ........-> Aggregate + ............-> Table "PUBLIC"."TDETL" as "D1C" Full Scan + Select Expression(line, column) + ....-> Aggregate + ........-> Nested Loop Join (inner) + ............-> Filter + ................-> Table "PUBLIC"."TMAIN" as "M2" Access By ID + ....................-> Index "PUBLIC"."TMAIN_PK" Full Scan + ........................-> Bitmap + ............................-> Index "PUBLIC"."TMAIN_X" Range Scan (lower bound: 1/1) + ............-> Filter + ................-> Table "PUBLIC"."TDETL" as "D" Access By ID + ....................-> Bitmap + ........................-> Index "PUBLIC"."TDETL_PK" Unique Scan + Sub-query + ....-> Filter + ........-> Table "PUBLIC"."TDETL" as "D" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TDETL_FK" Range Scan (full match) + Select Expression(line, column) + ....-> Filter + ........-> Table "PUBLIC"."TMAIN" as "M3" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TMAIN_X" Range Scan (lower bound: 1/1) + ......0 ms + """ + + 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 From 4f5b76a4e908dca33379d8dac9b799f086374da1 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 19:10:01 +0300 Subject: [PATCH 1045/1064] Added/Updated tests\bugs\gh_7466_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7466_test.py | 80 +++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/tests/bugs/gh_7466_test.py b/tests/bugs/gh_7466_test.py index df8b51a2..d0510eea 100644 --- a/tests/bugs/gh_7466_test.py +++ b/tests/bugs/gh_7466_test.py @@ -14,36 +14,39 @@ No errors must present in the trace log. All created units must be specified in blocks related to compilation. NOTES: [17-aug-2023] pzotov - ::: NB ::: - 0. This test DOES NOT check tracking of plans for queries inside those PSQL modules (i.e. strarting ticket issue, - see: https://github.com/FirebirdSQL/firebird/pull/7466#issue-1564439735 ). - SEPARATE TEST WILL BE IMPLEMENTED FOR THAT. - 1. It must be noted that the term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action - occurs when unit code is loaded into metadata cache. - 2. Procedures and functions are loaded into metadata cache immediatelly when they are created. - 3. Triggers are loaded into metadata cache in 'deferred' way, when something occurs that causes trigger to fire. - So, DML trigger will fire when we do (for example) INSERT, DB_level trigger - when we do some action on DB level - (e.g. connect/disconnect), and similar to DDL trigger. - 4. Currently there is no way to specify in the trace what EXACT type of DDL trigger fired. It is shown as "AFTER DDL". - 5. Lot of system-related triggers are displayed in the trace log during creating user-defined units: - Trigger RDB$TRIGGER_26 FOR RDB$RELATION_CONSTRAINTS - Trigger RDB$TRIGGER_18 FOR RDB$INDEX_SEGMENTS (BEFORE UPDATE) - Trigger RDB$TRIGGER_8 FOR RDB$USER_PRIVILEGES (BEFORE DELETE) - etc. Test ignores them and takes in account only triggers that have been creates by "our" SQL script. - 6. User-defined DDL trigger will be loaded into metadata cache MULTIPLE times (three in this test: for create view, - its altering and its dropping - although there is no re-connect between these actions). This is conisdered as bug, - see: https://github.com/FirebirdSQL/firebird/pull/7426 (currently it is not yet fixed). - - Checked on 5.0.0.1164. - Thanks to dimitr for explanations. - Discussed with dimitr, letters 17.08.2023. + ::: NB ::: + 0. This test DOES NOT check tracking of plans for queries inside those PSQL modules (i.e. strarting ticket issue, + see: https://github.com/FirebirdSQL/firebird/pull/7466#issue-1564439735 ). + SEPARATE TEST WILL BE IMPLEMENTED FOR THAT. + 1. The term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action + occurs when unit code is loaded into metadata cache. + 2. Procedures and functions are loaded into metadata cache immediatelly when they are created. + 3. Triggers are loaded into metadata cache in 'deferred' way, when something occurs that causes trigger to fire. + So, DML trigger will fire when we do (for example) INSERT, DB_level trigger - when we do some action on DB level + (e.g. connect/disconnect), and similar to DDL trigger. + 4. Currently there is no way to specify in the trace what EXACT type of DDL trigger fired. It is shown as "AFTER DDL". + 5. Lot of system-related triggers are displayed in the trace log during creating user-defined units: + Trigger RDB$TRIGGER_26 FOR RDB$RELATION_CONSTRAINTS + Trigger RDB$TRIGGER_18 FOR RDB$INDEX_SEGMENTS (BEFORE UPDATE) + Trigger RDB$TRIGGER_8 FOR RDB$USER_PRIVILEGES (BEFORE DELETE) + etc. Test ignores them and takes in account only triggers that have been creates by "our" SQL script. + 6. User-defined DDL trigger will be loaded into metadata cache MULTIPLE times (three in this test: for create view, + its altering and its dropping - although there is no re-connect between these actions). This is conisdered as bug, + see: https://github.com/FirebirdSQL/firebird/pull/7426 (currently it is not yet fixed). + + Checked on 5.0.0.1164. + Thanks to dimitr for explanations. + Discussed with dimitr, letters 17.08.2023. [06-sep-2023] pzotov - Changed expected output: DDL trigger is loaded into metadata cache only once, so we have to check only SINGLE - occurence of "Trigger TRG_DDL (AFTER DDL)" event. - See also: https://github.com/FirebirdSQL/firebird/commit/00c2d10102468d5494b413c0de295079f62a27ec - - Checkec on 5.0.0.1190 + Changed expected output: DDL trigger is loaded into metadata cache only once, so we have to check only SINGLE + occurence of "Trigger TRG_DDL (AFTER DDL)" event. + See also: https://github.com/FirebirdSQL/firebird/commit/00c2d10102468d5494b413c0de295079f62a27ec + Checked on 5.0.0.1190 + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668. """ import locale import re @@ -61,7 +64,12 @@ 'log_trigger_compile = true', ] -allowed_patterns = [ ' ERROR AT ', 'Trigger TRG_', 'Procedure (SP_TEST|PG_TEST.PG_SP_WORKER)', 'Function (FN_TEST|PG_TEST.PG_FN_WORKER)' ] +allowed_patterns = [ + ' ERROR AT ', + 'Trigger ("PUBLIC".)?(")?TRG_', + 'Procedure ("PUBLIC".)?(")?(SP_TEST|PG_TEST(")?.(")?PG_SP_WORKER(")?)', + 'Function ("PUBLIC".)?(")?(FN_TEST|PG_TEST(")?.(")?PG_FN_WORKER)' +] allowed_patterns = [ re.compile(r, re.IGNORECASE) for r in allowed_patterns] @pytest.mark.trace @@ -267,7 +275,7 @@ def test_1(act: Action, capsys): if p.search(line): print(line.strip()) - expected_stdout = f""" + expected_stdout_5x = f""" Procedure SP_TEST: Procedure PG_TEST.PG_SP_WORKER: Function FN_TEST: @@ -277,6 +285,16 @@ def test_1(act: Action, capsys): Trigger TRG_DDL (AFTER DDL): """ - act.expected_stdout = expected_stdout + expected_stdout_6x = f""" + Procedure "PUBLIC"."SP_TEST": + Procedure "PUBLIC"."PG_TEST"."PG_SP_WORKER": + Function "PUBLIC"."FN_TEST": + Function "PUBLIC"."PG_TEST"."PG_FN_WORKER": + Trigger "PUBLIC"."TRG_DB_CONN" (ON CONNECT): + Trigger "PUBLIC"."TRG_TEST_BIU" FOR "PUBLIC"."TEST" (BEFORE INSERT): + Trigger "PUBLIC"."TRG_DDL" (AFTER DDL): + """ + + 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 From 1fa1a99505f21888edcc8a8cae8c10ced5ad50e0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 19:14:10 +0300 Subject: [PATCH 1046/1064] Added/Updated tests\bugs\gh_7499_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7499_test.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_7499_test.py b/tests/bugs/gh_7499_test.py index 94583494..d4f4b78a 100644 --- a/tests/bugs/gh_7499_test.py +++ b/tests/bugs/gh_7499_test.py @@ -11,9 +11,12 @@ Restore from this .fbk must finish with WARNING and display name of that index. NOTES: [30.03.2023] pzotov - Unfortunately, I could not find DDL that leads not only to warning (on FB builds after fix) - but also to "gbak: ERROR" if we try to restore from this .fbk on FB builds *before* this - problem was fixed: 'gbak -rep' on all major FB just silently finished w/o any message. + Unfortunately, I could not find DDL that leads not only to warning (on FB builds after fix) + but also to "gbak: ERROR" if we try to restore from this .fbk on FB builds *before* this + problem was fixed: 'gbak -rep' on all major FB just silently finished w/o any message. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -28,12 +31,6 @@ act = python_act('db') -expected_stdout = """ - gbak: WARNING:index T2_FLD cannot be used in the specified plan - gbak:finishing, closing, and going home - gbak:adjusting the ONLINE and FORCED WRITES flags -""" - fbk_file = temp_file('gh_7499.tmp.fbk') @pytest.mark.version('>=3.0.11') @@ -56,6 +53,14 @@ def test_1(act: Action, fbk_file: Path, capsys): if act.match_any(line.strip(), allowed_patterns): print(line) + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + INDEX_NAME = 'T2_FLD' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"T2_FLD"' + expected_stdout = f""" + gbak: WARNING:index {INDEX_NAME} cannot be used in the specified plan + gbak:finishing, closing, and going home + gbak:adjusting the ONLINE and FORCED WRITES flags + """ act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From fe523966b04525e5164b65b7d99c96f13a1375ae Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 19:48:23 +0300 Subject: [PATCH 1047/1064] Added/Updated tests\bugs\gh_7506_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7506_test.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/tests/bugs/gh_7506_test.py b/tests/bugs/gh_7506_test.py index 44935dcd..0cde411d 100644 --- a/tests/bugs/gh_7506_test.py +++ b/tests/bugs/gh_7506_test.py @@ -10,9 +10,12 @@ 1) role. NOTES: [15.05.2025] pzotov - Additional subs for suppress excessive lines from 'show grants' output: remain only rows that contain prefix 'TMP_GH_7506_'. - Replaced expected-out text: use f-syntax with reference to user/role names provided by action instance instead of hardcoding them. - Checked on 6.0.0.778; 5.0.3.1649. Initial check was 24-apr-2023 on 5.0.0.1030. + Additional subs for suppress excessive lines from 'show grants' output: remain only rows that contain prefix 'TMP_GH_7506_'. + Replaced expected-out text: use f-syntax with reference to user/role names provided by action instance instead of hardcoding them. + Checked on 6.0.0.778; 5.0.3.1649. Initial check was 24-apr-2023 on 5.0.0.1030. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668. """ import pytest from firebird.qa import * @@ -30,6 +33,7 @@ @pytest.mark.version('>=5.0') def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: Role, tmp_role_mngr: Role, capsys): + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'PUBLIC.' test_user_sql = f""" recreate table test(id int primary key, f01 int, f02 int, f03 int, f04 int, f05 int, f06 int); recreate view v_test as select * from test; @@ -53,11 +57,11 @@ def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: """ act.expected_stdout = f""" - GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON TEST TO USER {tmp_user_boss.name.upper()} - GRANT SELECT, UPDATE (F04, F05, F06) ON TEST TO USER {tmp_user_boss.name.upper()} WITH GRANT OPTION - GRANT SELECT ON TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} - GRANT UPDATE (F01, F03) ON TEST TO USER {tmp_user_mngr.name.upper()} - GRANT UPDATE (F04, F05, F06) ON TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} + GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON {SQL_SCHEMA_PREFIX}TEST TO USER {tmp_user_boss.name.upper()} + GRANT SELECT, UPDATE (F04, F05, F06) ON {SQL_SCHEMA_PREFIX}TEST TO USER {tmp_user_boss.name.upper()} WITH GRANT OPTION + GRANT SELECT ON {SQL_SCHEMA_PREFIX}TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} + GRANT UPDATE (F01, F03) ON {SQL_SCHEMA_PREFIX}TEST TO USER {tmp_user_mngr.name.upper()} + GRANT UPDATE (F04, F05, F06) ON {SQL_SCHEMA_PREFIX}TEST TO USER {tmp_user_mngr.name.upper()} GRANTED BY {tmp_user_boss.name.upper()} """ act.isql(input = test_user_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout @@ -91,11 +95,11 @@ def test_1(act: Action, tmp_user_boss: User, tmp_user_mngr: User, tmp_role_boss: """ act.expected_stdout = f""" - GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON TEST TO ROLE {tmp_role_boss.name} - GRANT SELECT, UPDATE (F04, F05, F06) ON TEST TO ROLE {tmp_role_boss.name} WITH GRANT OPTION - GRANT SELECT ON TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} - GRANT UPDATE (F01, F03) ON TEST TO ROLE {tmp_role_mngr.name} - GRANT UPDATE (F04, F05, F06) ON TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} + GRANT DELETE, INSERT, UPDATE (F01, F02, F03) ON {SQL_SCHEMA_PREFIX}TEST TO ROLE {tmp_role_boss.name} + GRANT SELECT, UPDATE (F04, F05, F06) ON {SQL_SCHEMA_PREFIX}TEST TO ROLE {tmp_role_boss.name} WITH GRANT OPTION + GRANT SELECT ON {SQL_SCHEMA_PREFIX}TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} + GRANT UPDATE (F01, F03) ON {SQL_SCHEMA_PREFIX}TEST TO ROLE {tmp_role_mngr.name} + GRANT UPDATE (F04, F05, F06) ON {SQL_SCHEMA_PREFIX}TEST TO ROLE {tmp_role_mngr.name} GRANTED BY {tmp_user_boss.name} GRANT {tmp_role_boss.name} TO {tmp_user_boss.name} """ act.isql(input = test_role_sql, combine_output = True) From a434573dc0822ffa76d193050460f88f16062951 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:08:31 +0300 Subject: [PATCH 1048/1064] Added/Updated tests\bugs\gh_7517_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7517_test.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_7517_test.py b/tests/bugs/gh_7517_test.py index 44d9b0b4..6d47b7ea 100644 --- a/tests/bugs/gh_7517_test.py +++ b/tests/bugs/gh_7517_test.py @@ -6,9 +6,12 @@ TITLE: Successful compiling of procedure with wrong PLAN(s) used by some of its statement(s) NOTES: [29.03.2023] pzotov - Code for reproducing was provided by dimitr, letter 29.03.2023 09:46. - Confirmed bug on 3.0.11.33665. - Cheched on 5.0.0.978; 4.0.3.2913; 3.0.11.33666 - all fine. + Code for reproducing was provided by dimitr, letter 29.03.2023 09:46. + Confirmed bug on 3.0.11.33665. + Checked on 5.0.0.978; 4.0.3.2913; 3.0.11.33666 - all fine. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -33,15 +36,17 @@ from t1; """ -expected_stdout = """ - Statement failed, SQLSTATE = 42000 - index T2_FLD cannot be used in the specified plan -""" - act = isql_act('db', test_script) @pytest.mark.version('>=3.0.11') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + INDEX_NAME = 'T2_FLD' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"T2_FLD"' + expected_stdout = f""" + Statement failed, SQLSTATE = 42000 + index {INDEX_NAME} cannot be used in the specified plan + """ act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From fc56ca97e6116e40a7a3cbb4488e62e515c797af Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:09:58 +0300 Subject: [PATCH 1049/1064] Added/Updated tests\bugs\gh_7398_test.py: Added substitution to suppress all except sqltype and fields name from SQLDA output. --- tests/bugs/gh_7398_test.py | 43 ++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/tests/bugs/gh_7398_test.py b/tests/bugs/gh_7398_test.py index 9d9e4dc5..218a8d93 100644 --- a/tests/bugs/gh_7398_test.py +++ b/tests/bugs/gh_7398_test.py @@ -7,26 +7,29 @@ DESCRIPTION: NOTES: [29.09.2024] pzotov - 1. Ineffective execution plan was up to 4.0.3.2840. - Since 4.0.3.2843 plan changed and is the same for all subsequent FB-4.x snapshots. - Commit: https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 - (13.09.2022 19:17, "More complete solution for #3357 and #7118") - - 2. Database provided in the ticket has too big size (~335 Mb). - Test uses much smaller DB that was created on basis of original one by - extraction of small portions of data from tables PCP_TIN_REC_MAT and INV_ETQ_MAT. - These tables in original DB have 114115 and 1351211 rows. - In DB that is used here these tables have 15000 and 30000 rows corresp. - NOT all constraints are used in the test DB. Particularly, following DDL were abandoned: - ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_EMP FOREIGN KEY (ID_EMP) REFERENCES SYS_EMP (ID_EMP); - ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_OP FOREIGN KEY (ID_OP) REFERENCES PCP_OP (ID_OP); - ALTER TABLE PCP_TIN_REC_MAT ADD CONSTRAINT FK_PCP_TIN_REC_MAT_MAT FOREIGN KEY (ID_MAT) REFERENCES INV_MAT (ID_MAT); - Test database have been backed up using 4.0.3.2840 and compressed to .zip file. - 3. Because of missed valuable part of source data, I'm not sure that this test verifies exactly ticket issue. - But in any case, using this test one may see difference in execution plan that is produced in 4.0.3.2840 and 4.0.3.2843. - And such difference also can be seen on original DB (although plans there differ from those which are in test DB). - - Checked on 6.0.0.471, 5.0.2.1519, 4.0.6.3157. + 1. Ineffective execution plan was up to 4.0.3.2840. + Since 4.0.3.2843 plan changed and is the same for all subsequent FB-4.x snapshots. + Commit: https://github.com/FirebirdSQL/firebird/commit/1b192404d43a15d403b5ff92760bc5df9d3c89c3 + (13.09.2022 19:17, "More complete solution for #3357 and #7118") + + 2. Database provided in the ticket has too big size (~335 Mb). + Test uses much smaller DB that was created on basis of original one by + extraction of small portions of data from tables PCP_TIN_REC_MAT and INV_ETQ_MAT. + These tables in original DB have 114115 and 1351211 rows. + In DB that is used here these tables have 15000 and 30000 rows corresp. + NOT all constraints are used in the test DB. Particularly, following DDL were abandoned: + ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_EMP FOREIGN KEY (ID_EMP) REFERENCES SYS_EMP (ID_EMP); + ALTER TABLE PCP_TIN_REC ADD CONSTRAINT FK_PCP_TIN_REC_OP FOREIGN KEY (ID_OP) REFERENCES PCP_OP (ID_OP); + ALTER TABLE PCP_TIN_REC_MAT ADD CONSTRAINT FK_PCP_TIN_REC_MAT_MAT FOREIGN KEY (ID_MAT) REFERENCES INV_MAT (ID_MAT); + Test database have been backed up using 4.0.3.2840 and compressed to .zip file. + 3. Because of missed valuable part of source data, I'm not sure that this test verifies exactly ticket issue. + But in any case, using this test one may see difference in execution plan that is produced in 4.0.3.2840 and 4.0.3.2843. + And such difference also can be seen on original DB (although plans there differ from those which are in test DB). + + Checked on 6.0.0.471, 5.0.2.1519, 4.0.6.3157. + [05.07.2025] pzotov + Added substitution to suppress all except sqltype and fields name from SQLDA output. + Checked on 6.0.0.892; 5.0.3.1668. """ import locale From 5c827ad564c09ebcfbd9ab22d126645fa80c00f7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:12:11 +0300 Subject: [PATCH 1050/1064] Fixed wrong version of checked FB 6.x in the `NOTES` section. --- tests/bugs/gh_7331_test.py | 2 +- tests/bugs/gh_7499_test.py | 2 +- tests/bugs/gh_7506_test.py | 2 +- tests/bugs/gh_7517_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/bugs/gh_7331_test.py b/tests/bugs/gh_7331_test.py index b3e325d0..00fc33b3 100644 --- a/tests/bugs/gh_7331_test.py +++ b/tests/bugs/gh_7331_test.py @@ -15,7 +15,7 @@ [04.07.2025] pzotov Separated expected output for FB major versions prior/since 6.x. No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. - Checked on 6.0.0.863; 5.0.3.1668. + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest diff --git a/tests/bugs/gh_7499_test.py b/tests/bugs/gh_7499_test.py index d4f4b78a..88d44f33 100644 --- a/tests/bugs/gh_7499_test.py +++ b/tests/bugs/gh_7499_test.py @@ -16,7 +16,7 @@ problem was fixed: 'gbak -rep' on all major FB just silently finished w/o any message. [04.07.2025] pzotov Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x - Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest diff --git a/tests/bugs/gh_7506_test.py b/tests/bugs/gh_7506_test.py index 0cde411d..537d2de5 100644 --- a/tests/bugs/gh_7506_test.py +++ b/tests/bugs/gh_7506_test.py @@ -15,7 +15,7 @@ Checked on 6.0.0.778; 5.0.3.1649. Initial check was 24-apr-2023 on 5.0.0.1030. [04.07.2025] pzotov Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x - Checked on 6.0.0.894; 5.0.3.1668. + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest from firebird.qa import * diff --git a/tests/bugs/gh_7517_test.py b/tests/bugs/gh_7517_test.py index 6d47b7ea..8dd28dd6 100644 --- a/tests/bugs/gh_7517_test.py +++ b/tests/bugs/gh_7517_test.py @@ -11,7 +11,7 @@ Checked on 5.0.0.978; 4.0.3.2913; 3.0.11.33666 - all fine. [04.07.2025] pzotov Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x - Checked on 6.0.0.894; 5.0.3.1668; 4.0.6.3214. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest From c3dbffd60f284fad1d7f6faa6f51249a21f2d6e5 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:16:27 +0300 Subject: [PATCH 1051/1064] Added/Updated tests\bugs\gh_7568_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7568_test.py | 76 +++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/tests/bugs/gh_7568_test.py b/tests/bugs/gh_7568_test.py index 62c3ce1b..c8d67987 100644 --- a/tests/bugs/gh_7568_test.py +++ b/tests/bugs/gh_7568_test.py @@ -6,9 +6,13 @@ TITLE: Equivalence of boolean condition in partial index NOTES: [03.02.2024] pzotov - Test is based on https://github.com/FirebirdSQL/firebird/pull/7987 - Confirmed problem on 6.0.0.244. - Checked on 6.0.0.247. + Test is based on https://github.com/FirebirdSQL/firebird/pull/7987 + Confirmed problem on 6.0.0.244. + Checked on 6.0.0.247. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.863. """ import pytest @@ -69,38 +73,42 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) - - PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) -""" - @pytest.mark.version('>=6.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_ASC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + PLAN (TEST INDEX (TEST_IDX_OFFER_DEC)) + """ + expected_stdout_6x = """ + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_ASC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + PLAN ("PUBLIC"."TEST" INDEX ("PUBLIC"."TEST_IDX_OFFER_DEC")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 67b72020b3a6603500041eb989498fb46affd2e8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:48:13 +0300 Subject: [PATCH 1052/1064] Added/Updated tests\bugs\gh_7604_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7604_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/bugs/gh_7604_test.py b/tests/bugs/gh_7604_test.py index c2dfb82c..9661b776 100644 --- a/tests/bugs/gh_7604_test.py +++ b/tests/bugs/gh_7604_test.py @@ -12,6 +12,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import locale import pytest @@ -42,8 +45,9 @@ def test_1(act: Action): select sp_test_func() as runtotal from rdb$database rows 0; """ - expected_stdout = """ - 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 52 WIN1251 + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 52 {SQL_SCHEMA_PREFIX}WIN1251 """ act.expected_stdout = expected_stdout From a99ebfc5e61fad1d3a8ba5f0595bb368dda831d8 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 20:51:00 +0300 Subject: [PATCH 1053/1064] Added/Updated gh_7610_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7610_test.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/bugs/gh_7610_test.py b/tests/bugs/gh_7610_test.py index ee5c466a..a2bdb530 100644 --- a/tests/bugs/gh_7610_test.py +++ b/tests/bugs/gh_7610_test.py @@ -14,15 +14,18 @@ Query 'select * from test' must fail with 'no permission for SELECT' error. NOTES: [03.06.2023] pzotov - BOTH problems (ability to query table and random numbers in rdb$system_privileges) could be reproduced only in OLD - snapshots, not in recent ones! - In FB 4.x last snapshot where *both* problems present is 4.0.0.2571 (20-aug-2021). In 4.0.0.2573 only problem with - random number in rdb$ exists, but user can no longer query table. - In 4.0.3.2948 (01-jun-2023) content of rdb$ is 0000000000000000. + BOTH problems (ability to query table and random numbers in rdb$system_privileges) could be reproduced only in OLD + snapshots, not in recent ones! + In FB 4.x last snapshot where *both* problems present is 4.0.0.2571 (20-aug-2021). In 4.0.0.2573 only problem with + random number in rdb$ exists, but user can no longer query table. + In 4.0.3.2948 (01-jun-2023) content of rdb$ is 0000000000000000. - In FB 5.x situation is similar: last snapshot with *both* problems is 5.0.0.1000 (02-apr-2023), and since 5.0.0.1001 - one may see only problem with numbers in rdb$, but they look 'constant': 3400000000000000, and this is so up to 5.0.0.1063. - Since 5.0.0.1065 (01-jun-2023) content of rdb$ is 0000000000000000. + In FB 5.x situation is similar: last snapshot with *both* problems is 5.0.0.1000 (02-apr-2023), and since 5.0.0.1001 + one may see only problem with numbers in rdb$, but they look 'constant': 3400000000000000, and this is so up to 5.0.0.1063. + Since 5.0.0.1065 (01-jun-2023) content of rdb$ is 0000000000000000. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -81,6 +84,8 @@ def test_1(act: Action, fbk_file: Path, tmp_user: User, tmp_role: Role, capsys): select * from test; """ + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_TEST_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' expected_stdout = f""" MON$USER {tmp_user.name.upper()} MON$ROLE {tmp_role.name.upper()} @@ -89,7 +94,7 @@ def test_1(act: Action, fbk_file: Path, tmp_user: User, tmp_role: Role, capsys): RDB$ROLE_NAME {tmp_role.name.upper()} RDB$SYSTEM_PRIVILEGES 0000000000000000 Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST + no permission for SELECT access to TABLE {TABLE_TEST_NAME} -Effective user is {tmp_user.name.upper()} """ From c9175ccc587df4f0aa1998c44921f21937b8aad7 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 21:54:58 +0300 Subject: [PATCH 1054/1064] Added/Updated tests\bugs\gh_7670_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7670_test.py | 95 +++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/tests/bugs/gh_7670_test.py b/tests/bugs/gh_7670_test.py index 536887c3..803cfc29 100644 --- a/tests/bugs/gh_7670_test.py +++ b/tests/bugs/gh_7670_test.py @@ -6,8 +6,12 @@ TITLE: Cursor name can duplicate parameter and variable names in procedures and functions DESCRIPTION: NOTES: - Confirmed bug on 4.0.3.2957, 5.0.0.1100: all statements from this test did not issue error. - Checked on 4.0.3.2966, 5.0.0.1121: all OK. + Confirmed bug on 4.0.3.2957, 5.0.0.1100: all statements from this test did not issue error. + Checked on 4.0.3.2966, 5.0.0.1121: all OK. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest @@ -83,36 +87,65 @@ act = isql_act('db', test_script) -expected_stdout = """ - Statement failed, SQLSTATE = 42000 - CREATE FUNCTION F1 failed - -Dynamic SQL Error - -SQL error code = -637 - -duplicate specification of A_NAME_IN_STANDALONE_FUNC - not supported - Statement failed, SQLSTATE = 42000 - CREATE PROCEDURE P1 failed - -Dynamic SQL Error - -SQL error code = -637 - -duplicate specification of A_NAME_IN_STANDALONE_PROC - not supported - Statement failed, SQLSTATE = 42000 - CREATE PROCEDURE P2 failed - -Dynamic SQL Error - -SQL error code = -637 - -duplicate specification of O_NAME_IN_STANDALONE_PROC - not supported - Statement failed, SQLSTATE = 42000 - RECREATE PACKAGE BODY PG1 failed - -Dynamic SQL Error - -SQL error code = -637 - -duplicate specification of A_NAME_IN_PACKAGED_FUNC - not supported - Statement failed, SQLSTATE = 42000 - RECREATE PACKAGE BODY PG2 failed - -Dynamic SQL Error - -SQL error code = -637 - -duplicate specification of A_NAME_IN_PACKAGED_PROC - not supported -""" - @pytest.mark.version('>=4.0.2') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + Statement failed, SQLSTATE = 42000 + CREATE FUNCTION F1 failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of A_NAME_IN_STANDALONE_FUNC - not supported + Statement failed, SQLSTATE = 42000 + CREATE PROCEDURE P1 failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of A_NAME_IN_STANDALONE_PROC - not supported + Statement failed, SQLSTATE = 42000 + CREATE PROCEDURE P2 failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of O_NAME_IN_STANDALONE_PROC - not supported + Statement failed, SQLSTATE = 42000 + RECREATE PACKAGE BODY PG1 failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of A_NAME_IN_PACKAGED_FUNC - not supported + Statement failed, SQLSTATE = 42000 + RECREATE PACKAGE BODY PG2 failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of A_NAME_IN_PACKAGED_PROC - not supported + """ + + expected_stdout_6x = """ + Statement failed, SQLSTATE = 42000 + CREATE FUNCTION "PUBLIC"."F1" failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of "A_NAME_IN_STANDALONE_FUNC" - not supported + Statement failed, SQLSTATE = 42000 + CREATE PROCEDURE "PUBLIC"."P1" failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of "A_NAME_IN_STANDALONE_PROC" - not supported + Statement failed, SQLSTATE = 42000 + CREATE PROCEDURE "PUBLIC"."P2" failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of "O_NAME_IN_STANDALONE_PROC" - not supported + Statement failed, SQLSTATE = 42000 + RECREATE PACKAGE BODY "PUBLIC"."PG1" failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of "A_NAME_IN_PACKAGED_FUNC" - not supported + Statement failed, SQLSTATE = 42000 + RECREATE PACKAGE BODY "PUBLIC"."PG2" failed + -Dynamic SQL Error + -SQL error code = -637 + -duplicate specification of "A_NAME_IN_PACKAGED_PROC" - not supported + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From cf396effbfba95c7931458d8d40ac89fe2105e1e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:04:15 +0300 Subject: [PATCH 1055/1064] Added/Updated tests\bugs\gh_7675_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7675_test.py | 121 +++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 45 deletions(-) diff --git a/tests/bugs/gh_7675_test.py b/tests/bugs/gh_7675_test.py index 27627c4a..b52439ec 100644 --- a/tests/bugs/gh_7675_test.py +++ b/tests/bugs/gh_7675_test.py @@ -8,13 +8,14 @@ Test only ckecks ability to use RDB$SQL package as it is described in the doc. More complex tests will be implemented later. NOTES: - [02.10.2023] pzotov - Checked on 6.0.0.65. - [17.11.2024] pzotov - Removed output of concrete data for checked query. - It is enough only to display content of SQLDA (lines with 'sqltype:' and 'name:') and SQLSTATE (if some error occurs). - Checked on 6.0.0.532. + Removed output of concrete data for checked query. + It is enough only to display content of SQLDA (lines with 'sqltype:' and 'name:') and SQLSTATE (if some error occurs). + Checked on 6.0.0.532. + [04.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909. """ import os @@ -50,46 +51,76 @@ act = isql_act('db', test_script, substitutions=[('^((?!SQLSTATE|sqltype:|name:).)*$',''),('[ \t]+',' ')]) -expected_stdout = """ - 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 - : name: PLAN_LINE alias: PLAN_LINE - - 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 - : name: RECORD_SOURCE_ID alias: RECORD_SOURCE_ID - - 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 - : name: PARENT_RECORD_SOURCE_ID alias: PARENT_RECORD_SOURCE_ID - - 04: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 - : name: LEVEL alias: LEVEL - - 05: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 - : name: OBJECT_TYPE alias: OBJECT_TYPE - - 06: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 - : name: PACKAGE_NAME alias: PACKAGE_NAME - - 07: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 - : name: OBJECT_NAME alias: OBJECT_NAME - - 08: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 - : name: ALIAS alias: ALIAS - - 09: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 - : name: CARDINALITY alias: CARDINALITY - - 10: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: RECORD_LENGTH alias: RECORD_LENGTH - - 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 - : name: KEY_LENGTH alias: KEY_LENGTH - - 12: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 UTF8 - : name: ACCESS_PATH alias: ACCESS_PATH -""" - @pytest.mark.version('>=6.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: PLAN_LINE alias: PLAN_LINE + + 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + : name: RECORD_SOURCE_ID alias: RECORD_SOURCE_ID + + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: PARENT_RECORD_SOURCE_ID alias: PARENT_RECORD_SOURCE_ID + + 04: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: LEVEL alias: LEVEL + + 05: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: OBJECT_TYPE alias: OBJECT_TYPE + + 06: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + : name: PACKAGE_NAME alias: PACKAGE_NAME + + 07: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 UTF8 + : name: OBJECT_NAME alias: OBJECT_NAME + + 08: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 UTF8 + : name: ALIAS alias: ALIAS + + 09: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + : name: CARDINALITY alias: CARDINALITY + + 10: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: RECORD_LENGTH alias: RECORD_LENGTH + + 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: KEY_LENGTH alias: KEY_LENGTH + + 12: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 UTF8 + : name: ACCESS_PATH alias: ACCESS_PATH + """ + + expected_stdout_6x = """ + 01: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: PLAN_LINE alias: PLAN_LINE + 02: sqltype: 580 INT64 scale: 0 subtype: 0 len: 8 + : name: RECORD_SOURCE_ID alias: RECORD_SOURCE_ID + 03: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 + : name: PARENT_RECORD_SOURCE_ID alias: PARENT_RECORD_SOURCE_ID + 04: sqltype: 496 LONG scale: 0 subtype: 0 len: 4 + : name: LEVEL alias: LEVEL + 05: sqltype: 500 SHORT Nullable scale: 0 subtype: 0 len: 2 + : name: OBJECT_TYPE alias: OBJECT_TYPE + 06: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 SYSTEM.UTF8 + : name: SCHEMA_NAME alias: SCHEMA_NAME + 07: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 SYSTEM.UTF8 + : name: PACKAGE_NAME alias: PACKAGE_NAME + 08: sqltype: 452 TEXT Nullable scale: 0 subtype: 0 len: 252 charset: 4 SYSTEM.UTF8 + : name: OBJECT_NAME alias: OBJECT_NAME + 09: sqltype: 448 VARYING Nullable scale: 0 subtype: 0 len: 1020 charset: 4 SYSTEM.UTF8 + : name: ALIAS alias: ALIAS + 10: sqltype: 480 DOUBLE Nullable scale: 0 subtype: 0 len: 8 + : name: CARDINALITY alias: CARDINALITY + 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: RECORD_LENGTH alias: RECORD_LENGTH + 12: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 + : name: KEY_LENGTH alias: KEY_LENGTH + 13: sqltype: 520 BLOB scale: 0 subtype: 1 len: 8 charset: 4 SYSTEM.UTF8 + : name: ACCESS_PATH alias: ACCESS_PATH + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 2d1741071758dfcf8b684f8d639f71e9224091c0 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:06:30 +0300 Subject: [PATCH 1056/1064] Added/Updated tests\bugs\gh_7676_test.py: Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7676_test.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_7676_test.py b/tests/bugs/gh_7676_test.py index b2c777f9..4b186032 100644 --- a/tests/bugs/gh_7676_test.py +++ b/tests/bugs/gh_7676_test.py @@ -7,8 +7,11 @@ DESCRIPTION: NOTES: [28.05.2024] pzotov - Confirmed bug on 5.0.0.1111: got SQLSTATE = HY000 / Attempt to evaluate index expression recursively - Checked on 5.0.0.1121. + Confirmed bug on 5.0.0.1111: got SQLSTATE = HY000 / Attempt to evaluate index expression recursively + Checked on 5.0.0.1121. + [04.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables - to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest @@ -26,14 +29,15 @@ act = isql_act('db', test_script, substitutions=[('[ \t]+', ' ')]) -expected_stdout = """ - Statement failed, SQLSTATE = 23000 - attempt to store duplicate value (visible to active transactions) in unique index "TEST_UNQ" - -Problematic key value is ( = 1) -""" - @pytest.mark.version('>=5.0.0') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + attempt to store duplicate value (visible to active transactions) in unique index {SQL_SCHEMA_PREFIX}"TEST_UNQ" + -Problematic key value is ( = 1) + """ act.expected_stdout = expected_stdout act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 26c6778551ba126f0f2c50ff8af4009c1dc270fd Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:09:43 +0300 Subject: [PATCH 1057/1064] Added/Updated tests\bugs\gh_7698_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7698_test.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/bugs/gh_7698_test.py b/tests/bugs/gh_7698_test.py index 65e73943..b63e894e 100644 --- a/tests/bugs/gh_7698_test.py +++ b/tests/bugs/gh_7698_test.py @@ -6,8 +6,12 @@ TITLE: The legacy plan with window functions is broken DESCRIPTION: NOTES: - Confirmed bug on 5.0.0.1149 - Checked on 5.0.0.1155 -- all OK. + Confirmed bug on 5.0.0.1149 + Checked on 5.0.0.1155 -- all OK. + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214; 3.0.13.33813. """ import pytest @@ -23,12 +27,16 @@ act = isql_act('db', test_script) -expected_stdout = """ - PLAN (RDB$RELATIONS NATURAL) -""" - @pytest.mark.version('>=3.0') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = """ + PLAN (RDB$RELATIONS NATURAL) + """ + expected_stdout_6x = """ + PLAN ("SYSTEM"."RDB$RELATIONS" NATURAL) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From 3b5e2d336479849730a89ef5829050ad23112858 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:14:00 +0300 Subject: [PATCH 1058/1064] Added/Updated tests\bugs\gh_7727_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7727_test.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/bugs/gh_7727_test.py b/tests/bugs/gh_7727_test.py index a75379a3..d0196ad1 100644 --- a/tests/bugs/gh_7727_test.py +++ b/tests/bugs/gh_7727_test.py @@ -7,8 +7,12 @@ DESCRIPTION: NOTES: [31.08.2023] pzotov - Confirmed problem on 5.0.0.1177, 4.0.4.2979 - Checked on 5.0.0.1183, 4.0.4.2983 (intermediate snapshots). + Confirmed problem on 5.0.0.1177, 4.0.4.2979 + Checked on 5.0.0.1183, 4.0.4.2983 (intermediate snapshots). + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -41,13 +45,18 @@ act = isql_act('db', test_script) -expected_stdout = f""" - PLAN JOIN (TA NATURAL, TB INDEX (PK_TEST_B)) - PLAN JOIN (TA NATURAL, TB INDEX (PK_TEST_B)) -""" - @pytest.mark.version('>=4.0.4') def test_1(act: Action): - act.expected_stdout = expected_stdout + + expected_stdout_5x = f""" + PLAN JOIN (TA NATURAL, TB INDEX (PK_TEST_B)) + PLAN JOIN (TA NATURAL, TB INDEX (PK_TEST_B)) + """ + expected_stdout_6x = f""" + PLAN JOIN ("TA" NATURAL, "TB" INDEX ("PUBLIC"."PK_TEST_B")) + PLAN JOIN ("TA" NATURAL, "TB" INDEX ("PUBLIC"."PK_TEST_B")) + """ + + act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x act.execute(combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From c5753fe6f312d55ee68325292890111d3504d65c Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:15:37 +0300 Subject: [PATCH 1059/1064] Added/Updated tests\bugs\gh_7730_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7730_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/bugs/gh_7730_test.py b/tests/bugs/gh_7730_test.py index 6ca076ac..e602aa08 100644 --- a/tests/bugs/gh_7730_test.py +++ b/tests/bugs/gh_7730_test.py @@ -13,6 +13,9 @@ Added 'SQLSTATE' in substitutions: runtime error must not be filtered out by '?!(...)' pattern ("negative lookahead assertion", see https://docs.python.org/3/library/re.html#regular-expression-syntax). Added 'combine_output = True' in order to see SQLSTATE if any error occurs. + [05.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import locale @@ -30,12 +33,14 @@ select timestamp '{CHK_TIMESTAMP}' from rdb$database; """ -expected_stdout = f""" - 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 128 charset: 0 NONE -""" @pytest.mark.version('>=4.0.4') def test_1(act: Action): + + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else 'SYSTEM.' + expected_stdout = f""" + 01: sqltype: 448 VARYING scale: 0 subtype: 0 len: 128 charset: 0 {SQL_SCHEMA_PREFIX}NONE + """ act.expected_stdout = expected_stdout act.isql(switches=['-q'], input = test_sql, combine_output = True, io_enc = locale.getpreferredencoding()) assert act.clean_stdout == act.clean_expected_stdout From 16b26992586546478247f66da2e396ec15e1442e Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:18:49 +0300 Subject: [PATCH 1060/1064] Added/Updated tests\bugs\gh_7744_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7744_test.py | 78 ++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/tests/bugs/gh_7744_test.py b/tests/bugs/gh_7744_test.py index 8074b095..752dd75c 100644 --- a/tests/bugs/gh_7744_test.py +++ b/tests/bugs/gh_7744_test.py @@ -14,8 +14,9 @@ After this we return SQL SECURITY attribute to 'DEFINER' and repeat the same. This attempt must complete with success. Finally, we DROP SQL SECURITY. This must again cause permission error for call of every PSQL units. NOTES: - [12.11.2023] pzotov - Checked on 6.0.0.122 + [05.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -32,41 +33,6 @@ @pytest.mark.version('>=6.0') def test_1(act: Action, u_senior: User, u_junior: User): - expected_stdout = f""" - RES_1 4.641588833612778892410076350919446 - RES_2 5.848035476425732131013574720275845 - RES_3 6.694329500821695218826593246399307 - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - - RES_7 8.879040017426007084292689552528769 - RES_8 9.283177667225557784820152701838891 - RES_9 9.654893846056297578599327844350667 - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - - Statement failed, SQLSTATE = 28000 - no permission for SELECT access to TABLE TEST - -Effective user is {u_junior.name} - """ - - act.expected_stdout = expected_stdout test_script = f""" set list on; connect '{act.db.dsn}' user {act.db.user} password '{act.db.password}'; @@ -194,5 +160,43 @@ def test_1(act: Action, u_senior: User, u_junior: User): rollback; """ + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_TEST_NAME = 'TEST' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TEST"' + + expected_stdout = f""" + RES_1 4.641588833612778892410076350919446 + RES_2 5.848035476425732131013574720275845 + RES_3 6.694329500821695218826593246399307 + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + + RES_7 8.879040017426007084292689552528769 + RES_8 9.283177667225557784820152701838891 + RES_9 9.654893846056297578599327844350667 + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + + Statement failed, SQLSTATE = 28000 + no permission for SELECT access to TABLE {TABLE_TEST_NAME} + -Effective user is {u_junior.name} + """ + + act.expected_stdout = expected_stdout act.isql(switches=['-q'], input = test_script, connect_db = False, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout From b0f0816ffe865f9a5e1cc2417ebe65a669c394df Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 22:26:28 +0300 Subject: [PATCH 1061/1064] Updated tests\bugs\gh_7749_test.py: adjust expected stdout/stderr to current FB version. --- tests/bugs/gh_7749_test.py | 254 ++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/tests/bugs/gh_7749_test.py b/tests/bugs/gh_7749_test.py index 5f4ad0fe..974e3c68 100644 --- a/tests/bugs/gh_7749_test.py +++ b/tests/bugs/gh_7749_test.py @@ -207,59 +207,58 @@ def test_1(act: Action, capsys): ^ """ - isql_show_expected_stdout = """ - DM_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8 Nullable - DM_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI Nullable - DM_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 Nullable - DM_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL Nullable - VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI Nullable - VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8 Nullable - VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 Nullable - VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL Nullable - NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 Nullable - NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR Nullable - BT_DEFAULT_CSET_IMPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET UTF8 COLLATE UNICODE_CI Nullable - BT_DEFAULT_CSET_EXPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET UTF8 COLLATE UTF8 Nullable - BT_NONDEF_CSET_IMPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET WIN1251 Nullable - BT_NONDEF_CSET_EXPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET WIN1251 COLLATE PXW_CYRL Nullable + isql_show_expected_stdout_6x = """ + PUBLIC.DM_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 Nullable + PUBLIC.DM_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI Nullable + PUBLIC.DM_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 Nullable + PUBLIC.DM_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL Nullable + VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI Nullable + VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 Nullable + VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 Nullable + VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL Nullable + NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 Nullable + NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR Nullable + BT_DEFAULT_CSET_IMPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI Nullable + BT_DEFAULT_CSET_EXPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 Nullable + BT_NONDEF_CSET_IMPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET SYSTEM.WIN1251 Nullable + BT_NONDEF_CSET_EXPLICIT_COLL BLOB segment 80, subtype TEXT CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL Nullable BLOB_BINARY BLOB segment 80, subtype BINARY Nullable - A_VC_DEFAULT_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI - A_VC_DEFAULT_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8 - A_VC_NONDEF_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET WIN1251 - A_VC_NONDEF_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL - A_NC_FIXED_CHAR_IMPLICIT_COLL INPUT CHAR(10) CHARACTER SET ISO8859_1 - A_NC_FIXED_CHAR_EXPLICIT_COLL INPUT CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR - A_BT_DEFAULT_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET UTF8 COLLATE UNICODE_CI - A_BT_DEFAULT_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET UTF8 COLLATE UTF8 - A_BT_NONDEF_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET WIN1251 - A_BT_NONDEF_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL - A_BLOB_BINARY INPUT BLOB CHARACTER SET NONE - O_VC_DEFAULT_CSET_IMPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI - O_VC_DEFAULT_CSET_EXPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8 - O_VC_NONDEF_CSET_IMPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET WIN1251 - O_VC_NONDEF_CSET_EXPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL - O_NC_FIXED_CHAR_IMPLICIT_COLL OUTPUT CHAR(10) CHARACTER SET ISO8859_1 - O_NC_FIXED_CHAR_EXPLICIT_COLL OUTPUT CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR - O_BT_DEFAULT_CSET_IMPLICIT_COLL OUTPUT BLOB CHARACTER SET UTF8 COLLATE UNICODE_CI - O_BT_DEFAULT_CSET_EXPLICIT_COLL OUTPUT BLOB CHARACTER SET UTF8 COLLATE UTF8 - O_BT_NONDEF_CSET_IMPLICIT_COLL OUTPUT BLOB CHARACTER SET WIN1251 - O_BT_NONDEF_CSET_EXPLICIT_COLL OUTPUT BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL - O_BLOB_BINARY OUTPUT BLOB CHARACTER SET NONE - OUTPUT (DM_VC_DEFAULT_CSET_EXPLICIT_COLL) VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI_AI - A_VC_DEFAULT_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UNICODE_CI - A_VC_DEFAULT_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8 - A_VC_NONDEF_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET WIN1251 - A_VC_NONDEF_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL - A_NC_FIXED_CHAR_IMPLICIT_COLL INPUT CHAR(10) CHARACTER SET ISO8859_1 - A_NC_FIXED_CHAR_EXPLICIT_COLL INPUT CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR - A_BT_DEFAULT_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET UTF8 COLLATE UNICODE_CI - A_BT_DEFAULT_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET UTF8 COLLATE UTF8 - A_BT_NONDEF_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET WIN1251 - A_BT_NONDEF_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL - A_BLOB_BINARY INPUT BLOB CHARACTER SET NONE + A_VC_DEFAULT_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + A_VC_DEFAULT_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + A_VC_NONDEF_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 + A_VC_NONDEF_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + A_NC_FIXED_CHAR_IMPLICIT_COLL INPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 + A_NC_FIXED_CHAR_EXPLICIT_COLL INPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR + A_BT_DEFAULT_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + A_BT_DEFAULT_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + A_BT_NONDEF_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.WIN1251 + A_BT_NONDEF_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + A_BLOB_BINARY INPUT BLOB CHARACTER SET SYSTEM.NONE + O_VC_DEFAULT_CSET_IMPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + O_VC_DEFAULT_CSET_EXPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + O_VC_NONDEF_CSET_IMPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 + O_VC_NONDEF_CSET_EXPLICIT_COLL OUTPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + O_NC_FIXED_CHAR_IMPLICIT_COLL OUTPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 + O_NC_FIXED_CHAR_EXPLICIT_COLL OUTPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR + O_BT_DEFAULT_CSET_IMPLICIT_COLL OUTPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + O_BT_DEFAULT_CSET_EXPLICIT_COLL OUTPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + O_BT_NONDEF_CSET_IMPLICIT_COLL OUTPUT BLOB CHARACTER SET SYSTEM.WIN1251 + O_BT_NONDEF_CSET_EXPLICIT_COLL OUTPUT BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + O_BLOB_BINARY OUTPUT BLOB CHARACTER SET SYSTEM.NONE + OUTPUT (PUBLIC.DM_VC_DEFAULT_CSET_EXPLICIT_COLL) VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI_AI + A_VC_DEFAULT_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + A_VC_DEFAULT_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + A_VC_NONDEF_CSET_IMPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 + A_VC_NONDEF_CSET_EXPLICIT_COLL INPUT VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + A_NC_FIXED_CHAR_IMPLICIT_COLL INPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 + A_NC_FIXED_CHAR_EXPLICIT_COLL INPUT CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR + A_BT_DEFAULT_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UNICODE_CI + A_BT_DEFAULT_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8 + A_BT_NONDEF_CSET_IMPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.WIN1251 + A_BT_NONDEF_CSET_EXPLICIT_COLL INPUT BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL + A_BLOB_BINARY INPUT BLOB CHARACTER SET SYSTEM.NONE """ - - act.expected_stdout = isql_show_expected_stdout + act.expected_stdout = isql_show_expected_stdout_6x act.isql(input = test_sql, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout act.reset() @@ -268,98 +267,99 @@ def test_1(act: Action, capsys): # Test N2: check extracted metadata (result of 'isql -x'). # ------- - isql_meta_expected_stdout = """ - CREATE DOMAIN DM_BLOB_BINARY AS BLOB SUB_TYPE 0 SEGMENT SIZE 80; - CREATE DOMAIN DM_BT_DEFAULT_CSET_EXPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET UTF8 COLLATE UTF8; - CREATE DOMAIN DM_BT_DEFAULT_CSET_IMPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80; - CREATE DOMAIN DM_BT_NONDEF_CSET_EXPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET WIN1251 COLLATE PXW_CYRL; - CREATE DOMAIN DM_BT_NONDEF_CSET_IMPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET WIN1251; - CREATE DOMAIN DM_NC_FIXED_CHAR_EXPLICIT_COLL AS CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR; - CREATE DOMAIN DM_NC_FIXED_CHAR_IMPLICIT_COLL AS CHAR(10) CHARACTER SET ISO8859_1; - CREATE DOMAIN DM_VC_DEFAULT_CSET_EXPLICIT_COLL AS VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8; - CREATE DOMAIN DM_VC_DEFAULT_CSET_IMPLICIT_COLL AS VARCHAR(10); - CREATE DOMAIN DM_VC_NONDEF_CSET_EXPLICIT_COLL AS VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL; - CREATE DOMAIN DM_VC_NONDEF_CSET_IMPLICIT_COLL AS VARCHAR(10) CHARACTER SET WIN1251; - CREATE TABLE TEST (VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + + isql_meta_expected_stdout_6x = """ + CREATE DOMAIN PUBLIC.DM_BLOB_BINARY AS BLOB SUB_TYPE 0 SEGMENT SIZE 80; + CREATE DOMAIN PUBLIC.DM_BT_DEFAULT_CSET_EXPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8; + CREATE DOMAIN PUBLIC.DM_BT_DEFAULT_CSET_IMPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80; + CREATE DOMAIN PUBLIC.DM_BT_NONDEF_CSET_EXPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL; + CREATE DOMAIN PUBLIC.DM_BT_NONDEF_CSET_IMPLICIT_COLL AS BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.WIN1251; + CREATE DOMAIN PUBLIC.DM_NC_FIXED_CHAR_EXPLICIT_COLL AS CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR; + CREATE DOMAIN PUBLIC.DM_NC_FIXED_CHAR_IMPLICIT_COLL AS CHAR(10) CHARACTER SET SYSTEM.ISO8859_1; + CREATE DOMAIN PUBLIC.DM_VC_DEFAULT_CSET_EXPLICIT_COLL AS VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8; + CREATE DOMAIN PUBLIC.DM_VC_DEFAULT_CSET_IMPLICIT_COLL AS VARCHAR(10); + CREATE DOMAIN PUBLIC.DM_VC_NONDEF_CSET_EXPLICIT_COLL AS VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL; + CREATE DOMAIN PUBLIC.DM_VC_NONDEF_CSET_IMPLICIT_COLL AS VARCHAR(10) CHARACTER SET SYSTEM.WIN1251; + CREATE TABLE PUBLIC.TEST (VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), + VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, BT_DEFAULT_CSET_IMPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80, - BT_DEFAULT_CSET_EXPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET UTF8 COLLATE UTF8, - BT_NONDEF_CSET_IMPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET WIN1251, - BT_NONDEF_CSET_EXPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET WIN1251 COLLATE PXW_CYRL, + BT_DEFAULT_CSET_EXPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + BT_NONDEF_CSET_IMPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.WIN1251, + BT_NONDEF_CSET_EXPLICIT_COLL BLOB SUB_TYPE TEXT SEGMENT SIZE 80 CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, BLOB_BINARY BLOB SUB_TYPE 0 SEGMENT SIZE 80); - CREATE OR ALTER FUNCTION FN_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + CREATE OR ALTER FUNCTION PUBLIC.FN_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), + A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, A_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, A_BLOB_BINARY BLOB) - RETURNS DM_VC_DEFAULT_CSET_EXPLICIT_COLL COLLATE UNICODE_CI_AI - CREATE OR ALTER PROCEDURE SP_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + RETURNS PUBLIC.DM_VC_DEFAULT_CSET_EXPLICIT_COLL COLLATE SYSTEM.UNICODE_CI_AI + CREATE OR ALTER PROCEDURE PUBLIC.SP_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), + A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, A_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, A_BLOB_BINARY BLOB) RETURNS (O_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - O_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - O_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - O_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - O_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - O_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + O_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + O_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + O_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + O_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + O_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, O_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - O_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - O_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - O_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + O_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + O_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + O_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, O_BLOB_BINARY BLOB) - ALTER FUNCTION FN_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + ALTER FUNCTION PUBLIC.FN_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), + A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, A_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, A_BLOB_BINARY BLOB) - RETURNS DM_VC_DEFAULT_CSET_EXPLICIT_COLL COLLATE UNICODE_CI_AI - ALTER PROCEDURE SP_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + RETURNS PUBLIC.DM_VC_DEFAULT_CSET_EXPLICIT_COLL COLLATE SYSTEM.UNICODE_CI_AI + ALTER PROCEDURE PUBLIC.SP_TEST (A_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), + A_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + A_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + A_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + A_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, A_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + A_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + A_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + A_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, A_BLOB_BINARY BLOB) RETURNS (O_VC_DEFAULT_CSET_IMPLICIT_COLL VARCHAR(10), - O_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET UTF8 COLLATE UTF8, - O_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251, - O_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET WIN1251 COLLATE PXW_CYRL, - O_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1, - O_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET ISO8859_1 COLLATE FR_FR, + O_VC_DEFAULT_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + O_VC_NONDEF_CSET_IMPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251, + O_VC_NONDEF_CSET_EXPLICIT_COLL VARCHAR(10) CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, + O_NC_FIXED_CHAR_IMPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1, + O_NC_FIXED_CHAR_EXPLICIT_COLL CHAR(10) CHARACTER SET SYSTEM.ISO8859_1 COLLATE SYSTEM.FR_FR, O_BT_DEFAULT_CSET_IMPLICIT_COLL BLOB, - O_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET UTF8 COLLATE UTF8, - O_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET WIN1251, - O_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET WIN1251 COLLATE PXW_CYRL, + O_BT_DEFAULT_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.UTF8 COLLATE SYSTEM.UTF8, + O_BT_NONDEF_CSET_IMPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251, + O_BT_NONDEF_CSET_EXPLICIT_COLL BLOB CHARACTER SET SYSTEM.WIN1251 COLLATE SYSTEM.PXW_CYRL, O_BLOB_BINARY BLOB) """ - act.expected_stdout = isql_meta_expected_stdout + act.expected_stdout = isql_meta_expected_stdout_6x act.extract_meta() assert act.clean_stdout == act.clean_expected_stdout From 6fd8c52676cfc1ca39820377b7b28424c83c3cdc Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 23:10:25 +0300 Subject: [PATCH 1062/1064] Added/Updated tests\bugs\gh_7804_test.py: Separated expected output for FB major versions prior/since 6.x. --- tests/bugs/gh_7804_test.py | 159 ++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 36 deletions(-) diff --git a/tests/bugs/gh_7804_test.py b/tests/bugs/gh_7804_test.py index a32e8cf8..8ffe4935 100644 --- a/tests/bugs/gh_7804_test.py +++ b/tests/bugs/gh_7804_test.py @@ -13,33 +13,10 @@ Number of NR must always be 0. Number of IR should increase in proportion to the number of 'OR' terms in the WHERE expression. NOTES: - [01.11.2023] pzotov - 0. ::: NB ::: TEST IS LIKELY TO BE SUPPLEMENTED WITH OTHER CASES. - 1. Explained plan must be displayed with preserved indents, see call to func replace_leading(). - 2. Statistics is gathered using con.info.get_table_access_stats() method. - One need to remember that values are cumulative, so we have make two 'snapshots', - before and after query execution, and then calculate difference between them. - - Checked on 6.0.0.101. - - [16.12.2023] pzotov - Adjusted output to recent changes in FB, currently only for FB 5.x. - See: - https://github.com/FirebirdSQL/firebird/commit/ae427762d5a3e740b69c7239acb9e2383bc9ca83 - More realistic cardinality adjustments for unmatchable booleans, this should also fix #7904: FB5 bad plan for query - - Output for FB 6.x will be changed later (letter from dimitr, 16.12.2023 10:32) - - [18.01.2025] pzotov - Resultset of cursor that executes using instance of selectable PreparedStatement must be stored - in some variable in order to have ability close it EXPLICITLY (before PS will be freed). - Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). - This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 - The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). - - [19.01.2025] pzotov - Result in 6.x became equal to 5.x. Removed separation of expected* output - Checked on 6.0.0.587-90401f7 + [05.07.2025] pzotov + Separated expected output for FB major versions prior/since 6.x. + No substitutions are used to suppress schema and quotes. Discussed with dimitr, 24.06.2025 12:39. + Checked on 6.0.0.909; 5.0.3.1668. """ import pytest @@ -145,7 +122,7 @@ def test_1(act: Action, capsys): #-------------------------------------------------------------------- - expected_out = f""" + expected_stdout_5x = f""" Query: {q_list[0]} Select Expression ....-> Filter @@ -155,7 +132,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 1000 - Query: select * from test where x = 3 or x = 2 + Query: {q_list[1]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -167,7 +144,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 2000 - Query: select * from test where x = 2 or x = 3 or x = 1 + Query: {q_list[2]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -182,7 +159,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 3000 - Query: select * from test where x = 2 or x is null or x = 3 or x = 1 + Query: {q_list[3]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -200,7 +177,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 4000 - Query: select * from test where x = 5 + Query: {q_list[4]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -209,7 +186,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 1000 - Query: select * from test where x = 6 or x = 5 + Query: {q_list[5]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -221,7 +198,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 2000 - Query: select * from test where x = 5 or x = 4 or x = 6 + Query: {q_list[6]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -236,7 +213,7 @@ def test_1(act: Action, capsys): NR: 0 IR: 3000 - Query: select * from test where x = 6 or x is null or x = 4 or x = 5 + Query: {q_list[7]} Select Expression ....-> Filter ........-> Table "TEST" Access By ID @@ -255,6 +232,116 @@ def test_1(act: Action, capsys): IR: 4000 """ - act.expected_stdout = expected_out + expected_stdout_6x = f""" + Query: {q_list[0]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + NR: 0 + IR: 1000 + + Query: {q_list[1]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + NR: 0 + IR: 2000 + + Query: {q_list[2]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + NR: 0 + IR: 3000 + + Query: {q_list[3]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap Or + ........................-> Bitmap + ............................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ........................-> Bitmap + ............................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_ASC" Range Scan (full match) + NR: 0 + IR: 4000 + + Query: {q_list[4]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap + ................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + NR: 0 + IR: 1000 + + Query: {q_list[5]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + NR: 0 + IR: 2000 + + Query: {q_list[6]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + NR: 0 + IR: 3000 + + Query: {q_list[7]} + Select Expression + ....-> Filter + ........-> Table "PUBLIC"."TEST" Access By ID + ............-> Bitmap Or + ................-> Bitmap Or + ....................-> Bitmap Or + ........................-> Bitmap + ............................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ........................-> Bitmap + ............................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ....................-> Bitmap + ........................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + ................-> Bitmap + ....................-> Index "PUBLIC"."TEST_X_DEC" Range Scan (full match) + NR: 0 + IR: 4000 + """ + + 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 From 96984428b986269389e0c0d79f60ecc1cbfb530b Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 23:14:00 +0300 Subject: [PATCH 1063/1064] Added/Updated tests\bugs\gh_7853_test.py: Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7853_test.py | 103 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/tests/bugs/gh_7853_test.py b/tests/bugs/gh_7853_test.py index a2d62b25..3880cffd 100644 --- a/tests/bugs/gh_7853_test.py +++ b/tests/bugs/gh_7853_test.py @@ -12,27 +12,24 @@ This behavior changed since snapshot 5.0.0.1304 (date: 16-dec-2023). NOTES: [17.12.2023] pzotov - 1. Explained plans for queries where 'tmain' have aliases 'm0' ... 'm4' have: - * 'Filter (preliminary)' - for snapshots before this fix - * 'Filter' (WITHOUT preliminary) - after fix - 2. Last commit in the push is "deterministic uncorrelated subqueries to be considered as invariants" - but there is NO DIFFERENCE - between explained plans for 5.x snapshots that belongs to time points just _before_ and _after_ this push. - This is because push of PR#7853 has several commits, and one of them did broke such functionality whereas next - commit - WITHIN THIS PUSH (!) - did restore previous state (letter by dimitr, 17.12.2023 21:17). - - 3. Actually, NON-correlated subqueries became considered as INVARIANT much earlier, since 5.0.0.890, 10-jan-2023 - ("Merge pull request #7441 from FirebirdSQL/v5-pretty-explained-plan", a6ce0ec1632ec037b41b9cbcad42fd3ce6a9ea5e). - It seems that this old commit (of 10-jan-2023) caused lot of old issues to be considered now as fixed, for example - https://github.com/FirebirdSQL/firebird/issues/3394 - Query where 'tmain' table has alias 'm4' (and 'tdetl' table is involved - in contrary to all other queries) - is from this ticket. - This query explained plan must have "Sub-query (invariant)" since build 5.0.0.890 - - Checked on 5.0.0.1304 - ::: NB ::: Build 6.0.0.180 - FAILS because this PR still not pushed in master branch. Waiting for commit. - - [18.11.2024] pzotov - Remove upper bound for version after this feature was front-ported to 6.x in commit 0d72b8097c292dabb5c9a257a157f20d9362ab26 (16.11.23). - Checked on 6.0.0.532. + 1. Explained plans for queries where 'tmain' have aliases 'm0' ... 'm4' have: + * 'Filter (preliminary)' - for snapshots before this fix + * 'Filter' (WITHOUT preliminary) - after fix + 2. Last commit in the push is "deterministic uncorrelated subqueries to be considered as invariants" - but there is NO DIFFERENCE + between explained plans for 5.x snapshots that belongs to time points just _before_ and _after_ this push. + This is because push of PR#7853 has several commits, and one of them did broke such functionality whereas next + commit - WITHIN THIS PUSH (!) - did restore previous state (letter by dimitr, 17.12.2023 21:17). + + 3. Actually, NON-correlated subqueries became considered as INVARIANT much earlier, since 5.0.0.890, 10-jan-2023 + ("Merge pull request #7441 from FirebirdSQL/v5-pretty-explained-plan", a6ce0ec1632ec037b41b9cbcad42fd3ce6a9ea5e). + It seems that this old commit (of 10-jan-2023) caused lot of old issues to be considered now as fixed, for example + https://github.com/FirebirdSQL/firebird/issues/3394 + Query where 'tmain' table has alias 'm4' (and 'tdetl' table is involved - in contrary to all other queries) - is from this ticket. + This query explained plan must have "Sub-query (invariant)" since build 5.0.0.890 + + [05.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' and variables to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -65,36 +62,6 @@ act = python_act('db') -expected_stdout = """ - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Table "TMAIN" as "M0" Full Scan - - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Table "TMAIN" as "M1" Full Scan - - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Table "TMAIN" as "M2" Full Scan - - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Table "TMAIN" as "M3" Full Scan - - Sub-query (invariant) - ....-> Singularity Check - ........-> Aggregate - ............-> Table "TDETL" as "D" Full Scan - Select Expression - ....-> Aggregate - ........-> Filter - ............-> Table "TMAIN" as "M4" Full Scan -""" #--------------------------------------------------------- def replace_leading(source, char="."): stripped = source.lstrip() @@ -108,6 +75,40 @@ def test_1(act: Action, capsys): with cur.prepare(q) as ps: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan .split('\n')]) ) + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + TABLE_TMAIN_NAME = '"TMAIN"' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TMAIN"' + TABLE_TDETL_NAME = '"TDETL"' if act.is_version('<6') else f'{SQL_SCHEMA_PREFIX}"TDETL"' + expected_stdout = f""" + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table {TABLE_TMAIN_NAME} as "M0" Full Scan + + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table {TABLE_TMAIN_NAME} as "M1" Full Scan + + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table {TABLE_TMAIN_NAME} as "M2" Full Scan + + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table {TABLE_TMAIN_NAME} as "M3" Full Scan + + Sub-query (invariant) + ....-> Singularity Check + ........-> Aggregate + ............-> Table {TABLE_TDETL_NAME} as "D" Full Scan + Select Expression + ....-> Aggregate + ........-> Filter + ............-> Table {TABLE_TMAIN_NAME} as "M4" Full Scan + """ + act.expected_stdout = expected_stdout act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout From 4a9b65185e83cd41a97e6012b7b1631e6ffc7376 Mon Sep 17 00:00:00 2001 From: pavel-zotov Date: Sat, 5 Jul 2025 23:16:43 +0300 Subject: [PATCH 1064/1064] Added/Updated tests\bugs\gh_7899_test.py: Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x --- tests/bugs/gh_7899_test.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/bugs/gh_7899_test.py b/tests/bugs/gh_7899_test.py index 5129a42a..f04ab99a 100644 --- a/tests/bugs/gh_7899_test.py +++ b/tests/bugs/gh_7899_test.py @@ -11,6 +11,9 @@ 6.0.0.186, commit 305c40a05b1d64c14dbf5f25f36c42c44c6392d9 5.0.1.1307, commit e35437e00687db9ed6add279cecb816dcdf8b07a 4.0.5.3042, commit f7b090043e8886ab6286f8d626dd1684dc09e3b8 + [05.07.2025] pzotov + Added 'SQL_SCHEMA_PREFIX' to be substituted in expected_* on FB 6.x + Checked on 6.0.0.909; 5.0.3.1668; 4.0.6.3214. """ import pytest @@ -20,18 +23,6 @@ act = python_act('db') -expected_stdout = """ - Statement failed, SQLSTATE = 23000 - violation of FOREIGN KEY constraint "TDETL_FK" on table "PERSISTENT_DETL" - -Foreign key reference target does not exist - -Problematic key value is ("ID" = 1) - - Statement failed, SQLSTATE = 23000 - violation of FOREIGN KEY constraint "TDETL_FK" on table "PERSISTENT_DETL" - -Foreign key reference target does not exist - -Problematic key value is ("ID" = 2) -""" - @pytest.mark.version('>=4.0.5') def test_1(act: Action): @@ -67,6 +58,19 @@ def test_1(act: Action): where not exists(select * from persistent_main m where m.id = d.id); """ + SQL_SCHEMA_PREFIX = '' if act.is_version('<6') else '"PUBLIC".' + expected_stdout = f""" + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "TDETL_FK" on table {SQL_SCHEMA_PREFIX}"PERSISTENT_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("ID" = 1) + + Statement failed, SQLSTATE = 23000 + violation of FOREIGN KEY constraint "TDETL_FK" on table {SQL_SCHEMA_PREFIX}"PERSISTENT_DETL" + -Foreign key reference target does not exist + -Problematic key value is ("ID" = 2) + """ + act.expected_stdout = expected_stdout act.isql(switches=['-q'], input = test_script, combine_output = True) assert act.clean_stdout == act.clean_expected_stdout